やっと出しました。めでたい
Scala祭で予告してたやつです
http://xuwei-k.github.io/slides/scala-js-matsuri/#25
scalapropsやmsgpack4zについてあまり知らない人は、以下の資料や記事を参照
- scalaprops含めた、property based testingについて以前発表した資料
- msgpack4zというmsgpackのScala用ライブラリを作った
- extension typeをサポートしたmsgpack4zの0.2.0をリリースした
それぞれ
- scalazは7.2.1 https://github.com/scalaz/scalaz/commit/d646388c573416f8
- scalapropsは0.3.0 https://github.com/scalaprops/scalaprops/commit/81b595b9e768a2ee9596
- msgpack4zは
- msgpack4z-coreが0.3.2 https://github.com/msgpack4z/msgpack4z-core/commit/101bdbbe4f70fb1e4
- msgpack4z-nativeが0.3.0 https://github.com/msgpack4z/msgpack4z-native/commit/052114a7915a
- msgpack4z-circeが0.2.2 https://github.com/msgpack4z/msgpack4z-circe/commit/265e1419777a0298a
です。上記は、これを書いてる2016-03-21時点の最新版ですが、特に大きな続けたくない理由なければ、今後のversionでもScala.jsサポートは続けるはずです。
公式サイトにもpull reqしておきました
- https://github.com/scala-js/scala-js-website/pull/250
- https://github.com/scala-js/scala-js-website/pull/259
なにを思ったか忘れたけどScala.jsにハマり出したのが2015年の12月くらいだった気がするので、結局3ヶ月近くかかりましたね。
1、2ヶ月経過したころには、それぞれScala.js対応できそうな目処はたっていたわけですが、主に一番時間かけたscalapropsで以下のようなことをしていたら、だいぶ時間がかかってしまいました。
- クロスビルドの細かい設定のこだわり
- テストのパラメータ調整
- パフォーマンスのためにLongをできるだけ避けてIntに変更
- Scala.js用に新たにTinyMTをJavaから移植 https://github.com/scalaprops/scalaprops/commit/f984293a9
- できるだけJVMとJSのコードがDRYになるように工夫
- ついでに微妙に新機能入れた(テストで時間が多くかかった順番を最後に表示)
- JVMのリフレクションで頑張ってた部分が無理かと思ったら、js.Dictionaryにキャストすれば何故かいける!?みたいな試行錯誤*1
TinyMTよくわかってないですが(ぉぃ)、既存のscalaprops内の普通の Mersenne Twisterでは超遅かった *2 ので
- 大量のLong使う必要ない。結構省メモリ(JVMのIntが4つのみ)
- それなりに乱数の性質がよい(?)。少なくとも、既存のscalapropsのテストが、乱数の精度が原因で失敗することがなかった。(もっと別のやつも試行錯誤したら、それだと精度が原因でテスト失敗した)
みたいな特徴がぴったりでした。ありがたい・・・
http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/TINYMT/index-jp.html
msgpack4zに関しては
- 使えないクラス( DataInputStreamと DataOutputStream )の処理相当をScalaで書きなおしたり
- Javaで書いていたclassがあったので、Scalaで書きなおしたり
- msgpackの仕様どおりというかJVMのセマンティクス正確に守るには "scalaJSSemantics ~= { _.withStrictFloats(true) }" というのが必要、というのを知る https://github.com/msgpack4z/msgpack4z-core/blob/v0.3.2/project/Build.scala#L51
- circeというScala.js対応しているjsonライブラリ用のbindingがあるので、それの対応もしたり
などしました。ちなみに、msgpack4z-nativeは、Scalazの依存くっついてこないで単体で(case classとの自動マッピングなどはないが)超シンプルなシリアライザ、デシリアライザとして使うこともできます。case classのマッピングやその他色んな機能欲しい場合は msgpack4z-core を使ってください。
そのうちscodec-msgpackと、JS上でのベンチマーク比較してみたいですね(?)
Scalazは、Scala.js対応しつつ、バイナリ互換保つの厳しいかな?と思いましたが、頑張ったらどうにかなりました。
あと、やってる途中でScala.jsそのもののバグ見つけたり、微妙に実装されてないclass見つけてpull reqしたりしました。
他にも、かなり色々な細かい知見が溜まったのだけれど、全部書いてられないので、このくらいにしておきます。
Scala.jsのライブラリを(JVM用と)クロスビルドすることに関しては、今のところ日本で一番くらいには詳しくなったのではないだろうか・・・。
自作ライブラリでは、もうあまりScala.js対応するべきやつなかった気がするので、やるとしたら他のやつ(Monocleとか?)について、気が向いたらpull reqするかもしれません。
Monocleは、ビルド設定は簡単に書けたけど、(scalacheckが残念なせいで?)テストが途中で固まる、みたいな状態です・・・Scalacheckつらい・・・。
あとは、Scala.js対応よりは、以前書いたScalazのテスト全面書き換え
Cogenが入った新しいscalacheckがリリースされたけれどバグってるみたいだし我慢の限界なのでscalazの全てのテストをscalapropsベースで書き換えたい件
をやるべきか否か・・・