Lensの全体像を簡潔に理解するための記事
LensのOpticsはいろいろあって混乱してくるけど、この記事は、いい感じに細かいところを捨象しているところが素晴らしい。
Windowsドライバ開発のメモ
- micro kernel
- 関数呼び出しではなく、message passing
- WDFが隠蔽化
- Driver Model
- DM
- KMDF
- UMDF (user modeで動く) reflector
- ハリウッドの圧力?
- Windows Driver Kit
- 開発ツールは最新版を使わないとはまる。
- 開発は敷居を高くしている。EV証明書とかが必要。1年おきに更新
- Windowsハードウェア認定 HCK
- ハードウェア制御libraryの充実 -> C#でできる。
- WinUSB
- Microsoft OS Descriptor
- Windows.Devicesクラス DOS API との決別
- UWP ほとんどのデバイスを制御できる
extensibleの小さなサンプルを書いてみた
モナドのスタックの取り回しが面倒に感じているので、そろそろ何とかしたいと思っていました。ここでようやく重い腰を上げて、extensible
にチャレンジです。ウェブ上にある情報は、複雑だったので、もっと小さなサンプルを書き下してみました。
mtl
とcompatible
の意味は、MonadReader
やMonadState
クラスを使って実装した場合を意味しています。Reader
モナドを直接使っている場合は、コードの修正が必要です。
extensible
の場合は、書き方が2通りあると思いますが(あってる?)、型クラス制約を使ったAssoicate
+TypeApplication
のパターンがベターと思いました。
小さなサンプルだと、extensible
の場合記述量が多くなり、まったくメリットは感じられませんが、規模が大きくなるとメリットが上回ると思います。
小さなサンプルが書けて、心理的障壁はなくなったので、今後は使っていくと思います。
NTextを指定してもTDSプロトコル用はvarcharになっている
なんでだろう?
using System; using System.Data; using System.Data.SqlClient; namespace ConsoleApp1 { class Program1 { static void Main(string[] args) { using (SqlConnection conn = new SqlConnection()) { conn.ConnectionString = "Server=DESKTOP-PA432R1;Database=TDS;User ID=sa;Password=haskellsa"; conn.Open(); SqlCommand command = NewMethod3(conn); using (SqlDataReader reader = command.ExecuteReader()) { Console.WriteLine("FirstColumn\tSecond Column\t\tThird Column\t\tForth Column\t"); while (reader.Read()) { Console.WriteLine(String.Format("{0} \t | {1} ", reader[0], reader[1])); } } Console.WriteLine("Data displayed! Now press enter to move to the next section!"); Console.ReadLine(); Console.Clear(); } Console.ReadLine(); } private static SqlCommand NewMethod3(SqlConnection conn) { SqlCommand command = new SqlCommand("select x_id, x_ntext from tds.dbo.tbl_string where x_ntext like @foo", conn); SqlParameter param = new SqlParameter("foo", SqlDbType.NText); param.Value = "abc"; command.Parameters.Add(param); return command; } } }
JavaParserを使ってみる
Javaのコードレビューをしていて、指摘事項の水平展開をする時に、エディタ等のgrepで検索して、類似の指摘箇所を探したりします。 ただ、それだと、複数行にまたがり相関をもった内容の抽出に手間がかかります。
例えば、前のプロジェクトでは、stream処理の中に、さらにstream処理を使っているケースでは、可読性が著しく下いコードがたくさんありました。当初は、一律禁止するつもりはなかったのですが、一律禁止することにしました。禁止するので、このルールが守られているかチェックが必要になり、grepでソースコードの当たりをつけて、その前後を目視確認する作業に手間がかかってしまいました。
なんらかのツールをカスタマイズすればよかったのですが、カスタマイズのルールを学ぶのが面倒だったので、結局、grep+目視をしていました。
結局、込み入ったチェックやプロジェクトのルールに従っていることをチェックをするには、Javaのソースコードをパースするしかありません(というか、各種ツールもパースしてますが)。
そこで、次回に活かせるようにJavaのソースコードをパースの練習をしてみました。
パーサーはJavaParserが良さそうだったので、使ってみました。基本的な使い方は、
- ソースコードを読み込み、
- Visitorを適用するだけです。
- 各種ノードに対するドメソッドがたくさん用意されているので、それをオーバーライド実装するだけです。
Visitorパターンなので、同じノードでも階層が異なった時の対処が面倒くさいのですが。
最初はどのようなノード構造になっているかわからないので、
- いったんパースした後のノードを全部出力しておく
- ツリーを出力しておく
と良いと思います。
下のコード例では、
- ノード全体の出力(デバッック用)
- ツリーをJSONとして表示(デバッック用)
- メソッドの行数(練習)
- forEachのなかにforEachがある部分(前のプロジェクトでチェックしたかった箇所)
を出力しています。
いろいろできると思います。
- 長いラムダ式を抽出
- 嘘をついている変数名の抽出(例、Mapなのに変数名がListとなっている)
- コメントだけを抜き出して、文章をチェックするとか(オフショア案件の時)
JOOXで要素をwrapする。
過去記事で、jooxを取り上げたました。これを案件で補助ツールとして使っています。一律にxmlを補正したい時や、xmlの記述がプロジェクトのルールに従っているかをチェックするためにつかっています。
JavaでjQueryライクにXMLを操作する - IT練習ノート
ただ、jQueryにあるwrap相当のものがありません。もちろん、完全に無いわけではありません。
Match tags = $(document).find("body"); tags.wrap("aaaa"); // OK
というような、タグをwrapすることはできます。しかし、属性があるタグをwrapするインターフェースがありません。次のコードは実行時エラーになります。
tags.wrap("<aaaa/>"); // NG tags.wrap("<aaaa id='abc'/>"); // NG
Matchインターフェースを実装したImplクラスを拡張もしたかったのですが、実装が正しく隠蔽化されているので、拡張する余地がないようい思えました。
仕方がないので、簡易メソッドを作成しました。
コードを示します。
嵌った点としては、異なる要素は直接追加できないことでした。
xml - Java: how to wrap all elements with <sometag> in org.w3c.dom? - Stack Overflow
Javaのstreamで嵌る
IntStream
とStream<T>
インターフェースに親子関係がない
java.lang.AutoCloseable java.util.stream.BaseStream<T,S> java.util.stream.DoubleStream java.util.stream.IntStream java.util.stream.LongStream java.util.stream.Stream<T>
そのために(?)、IntSteram
に3つの引数をもつreduce
がない。これに気がつかず、相当時間を無駄にした。
順次および並列の集約操作をサポートするプリミティブint値要素のシーケンスです。これは、Streamに対してintプリミティブ特殊化を行ったものです。
とドキュメントにはあるが、特殊化といっても型だけ特殊化されているのではない。
多分、このようなクラス階層になっているのは、IntStream
はInteger
ではなくint
だからなんだろうけど。
Stream
インターフェースの2つの引数を持つreduce
と3つの引数を持つreduce
で2番目のパラメータ部分の型が異なる。
2引数
reduce(T identity, BinaryOperator
accumulator)
3引数
reduce(U identity, BiFunction; < U,? super T,U > accumulator, BinaryOperator < U > combiner)
2引数の場合、BinaryOperator
の型がT
なので、accumlator
の型はStream
の型と同じ必要がある。
また、実際のコーディングでは、3引数のcombiner
のコーディングが定型的になる(と思うので)冗長になる。
intelliJで型推論が微妙にずれている
3引数reduce
でパラメータの3番目が間違っているのに、2番目のエラーがでる。javacでは3番目のパラメータのコンパイルエラーになる。
単位元?
T reduce(T identity, BinaryOperator
accumulator) 指定された単位元の値と結合的な累積関数を使ってこのストリームの要素に対してリダクションを実行し、リデュースされた値を返します。これは、次の操作に相当します。
足し算の単位元は0だけど、0でなくても動作する。
int r = Stream.of(1,2,3).reduce(10, (x,y) -> x + y); System.out.println(r); // 16
サンプル
Snake case
とCamel case
の返還をstream
やラムダで書くといい感じになるかなと思ったのですが、そうでもないですね。
private static String toCamel(String str) { return Arrays.stream(str.split("_")) .map(x -> x.substring(0,1).toUpperCase() + x.substring(1).toLowerCase()) .collect(Collectors.joining()); } private static String toSnake(String in) { String out = in.codePoints() .mapToObj(c -> (char)c) // IntStream to Stream<Character> .reduce("" , (acc, v) -> acc + (Character.isLowerCase(v) ? v : "_" + Character.toLowerCase(v)) , (s1, s2) -> s1 + s2 ); return out; }
もっと簡潔にかけるのなら教えて下さい。
感想
Java
のstream
は、慣れてないだけかもしれないが、難しい。というか面倒。
reduce
は可読性が上がらなさそう。結局2変数の関数を作らないといけないこともあるので。
stream
処理を考えた時には、reduce
を使わない範囲で使うと良いのではないか。
reduce
使うくらいならfor
でループして処理するのが良さそう。