java-object-diff を F# に移植
久しぶりの移植芸です。
移植理由
Persimmonの開発に必要みたいな話になり、かつ移植する時間のありそうな人間が他にいなかったとかそういう。
先達
https://github.com/SQiShER/java-object-diff
さすがJavaさん、探せばだいたいでてくる。
成果物
https://github.com/pocketberserker/FSharp.Object.Diff
3月中旬に始めたので、まともに動かせるようになるまで二か月かかった計算に。 まぁ、FSDNやら業務のあれそれやら遊びといったことを考えると妥当な数値っぽい感じがしますね?
あれそれ
移植元はJavaなので、Javaを前提に実装されているわけですね。 なので、当然仕様の差が出てきます。
- Javaにプロパティはないが、.NETにはある
- フィールドのdiff取得機能はomit
- F#では必要ないと思うんだ
このあたりは仕様の話。
ここから実装の時に遭遇した(または現在進行形)の問題。
- Javaの一部のMapだとkeyにnullが突っ込める
- .NETのDictionaryは突っ込めないんだよねーとなってちょっと悩んだ
- Map.getでnullが返ってくる
- そういえばそんなんだったなーとか
- null nullしている
- Javaだもんね、仕方ないね
- 移植を優先した関係で F# 版もnull nullしてます…
- Some nullさん…
- F#のレコードがほぼ使えない
- 移植元がmutable前提なのでしょうがない
- abstract classが出てくるとレコード使えないしね
- .NETのコレクションの基底となるインターフェースは?
- .NETの連想配列の基底となるインターフェースは?
- 比較演算子とか
- Javaの
==
はObject.ReferenceEqual
に、equals
は=
に読み替えるの、わりと難しい - これをミスして何度か嵌った
- Javaの
- equality制約を回避したい
- F#だと
=
を使うと型パラメータがequality
制約を要求する - が、diffライブラリなのでそんな制約は外したい
- ので、比較する部分で
box x
を挟んでobj
で比較するバッドノウハウを駆使して制約を回避している
- F#だと
まとめ
nullよりもコレクションの仕様の差やtype eraseかそうでないかなど、もっと別な場所で精神が削れました。