最近コード書いていて、若干無理に抽象化を進めたら、なんかLensが必要になったけれど、いざScalaでLensを使うとなると果たしてどれを使えばいいのかすぐに判断できなかったので、いい機会なのでまとめてみる。
「ちなみに、これ書いた時点のまとめだし、すぐ古くなるかもしれないし、抜けてるものもあるかもしれないよ!」といういつもどおりの注意書きを書いておきます。
2015年3月に追記案の定古くなったので、あまり参考にしないほうがいいよ!
- Scalaz https://github.com/scalaz/scalaz/blob/v7.0.0/core/src/main/scala/scalaz/Lens.scala
- 7にも6にもあるが、
もういい加減finalでそうだしfinalでたし、使うとしたら7でしょう - 良くも悪くも
sealed trait LensFamily[-A1, +A2, +B1, -B2]
というように、ほかのものに比べてより抽象化されている - おそらく唯一(?) PartialLens もある
- 他にもメソッドがとにかく大量にあったり、Scalazを使うならば他のものとの親和性などで明らかに有利なはず
- 逆に、「Scalazには興味がなく、Lensだけちょっと使いたい人」にとっては、依存が重すぎるかも・・・?
- 7にも6にもあるが、
- shapeless https://github.com/milessabin/shapeless/blob/shapeless-1.2.4/core/src/main/scala/shapeless/lenses.scala
- Scalazに比べれば単純(?)
- Scalazに比べれば、Lens自体を定義するのが簡単なのが利点(?)
- 定義するのが簡単な割には、(後述するものと異なり)macroやcompiler pluginなどを何も使っていないのが特徴(implicitは大量に使っているが)
- akisaarinen/rillit https://github.com/akisaarinen/rillit
- macroとdynamicを使ってる
- 本人によるblog記事 http://akisaarinen.fi/blog/2012/12/07/boilerplate-free-functional-lenses-for-scala/
- 詳しい特徴は知りません、すいません・・・
- (これ書いてる時点では)最終更新が4ヶ月前で、2.10.0-RC5のままで、なおかつissueやpull reqが0なので、あまり使われてなさそうだなぁ・・・とちょっと不安
- これ書いてる時点では、sonatypeなどではなくgh-pagesにjar置いてある
- travisbrown/rillit https://github.com/travisbrown/rillit
- akisaarinen/rillit から fork して、shapeless対応したもの
- jarがpublishされてない・・・?
- hexx/lenser https://github.com/hexx/lenser
- 同僚・・・
- これも macroとdynamic
- rillitとの比較とか書きたいけど、調べるのめんどうだったのであとで気が向いたら書く・・・。もしくは知ってたらだれか教えて下さい。
- retronym/macrocosm https://github.com/retronym/macrocosm/blob/a73e81aee7d99c/src/main/scala/com/github/retronym/macrocosm/Macrocosm.scala#L361-L427
- ライブラリのかたちになってないけど、一応言及
- たぶん、akisaarinen/rillitやhexx/lenserのもとになったというか、影響をあたえたもの
- ほかにも、この macro + dynamic のパターン探せばありそうですね
- gseitz/Lensed https://github.com/gseitz/Lensed
- compiler pluginで、Scalaz6のLensを自動生成?
- (これ書いてる時点では)最終更新1年以上まえ・・・これも使われてないのか・・・
- 同じ方法で、だれかScalaz7のLensを生成するものは作ってないんです?
他にもあったら教えて下さい。
現状個人的な感覚としては
- Lensそんなに使いこなして理解してるわけじゃないけど、とにかくsetterとgetterの関数*1が、ファーストクラスで欲しい。*2
- 普段からScalaz7使ってるので、できればScalaz7のLens使いたい
- けど、おそらくScalaz7のLensは、上記にあげたなかで一番定義するのが面倒
- shapelessは定義するのが簡単で便利なのだけれど、たいしたことしないのに、わざわざshapelessの依存増やすのがちょっと躊躇われる
- ほかのものはそれほど使われてなさそうという点が・・・
- あと、macroやcomplier plugin使っているのは、必要以上に複雑性を持ち込む気がするので*3 *4 、(大きな利点がないなら)ちょっと避けたいという思いがある(単に、なんとなく理解していないので不安という感じなので、もっと調べたり使ってみないとわからないが)
- とりあえず、(ほかに誰か作ってないなら) Scalaz7のLensを、macroもしくはcompiler pluginで自動生成するものを作るべきでは・・・!?
- このままだと、もっと乱立しそうなので、もうちょっと議論まとめたりする人でてこないかな・・・(他力本願)
追記:
これ書いたことにより(?)なんかできてた https://github.com/hexx/scalaz-lenser