ScalaでのLens実装まとめ

最近コード書いていて、若干無理に抽象化を進めたら、なんかLensが必要になったけれど、いざScalaでLensを使うとなると果たしてどれを使えばいいのかすぐに判断できなかったので、いい機会なのでまとめてみる。


「ちなみに、これ書いた時点のまとめだし、すぐ古くなるかもしれないし、抜けてるものもあるかもしれないよ!」といういつもどおりの注意書きを書いておきます。

2015年3月に追記案の定古くなったので、あまり参考にしないほうがいいよ!



  • hexx/lenser https://github.com/hexx/lenser
    • 同僚・・・
    • これも macroとdynamic
    • rillitとの比較とか書きたいけど、調べるのめんどうだったのであとで気が向いたら書く・・・。もしくは知ってたらだれか教えて下さい。
  • 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

*1:ここで言ってるのは、もちろんimmutableなものです。case classの一つのfieldを違う値にして、新しいオブジェクトを返す。それと、case classの一つのfieldを取得する関数

*2:どう頑張っても、現状のScalaでは、macroやcompiler plugin使って工夫したり、自分で定義しないと無理

*3:あと、macroがまだexperimentalだったり

*4:コンパイラプラグインは、普通のライブラリに比べて、互換性保つのが難しい気がするし、メンテするとなると、コンパイラ内部のclassの知識が必要になって、それが負担