今更Scala 2と3でcase classのunapplyの非互換をどうにかするものをライブラリにした

4年近く前に以下のような記事を書きましたが、それを微妙に改変してライブラリにしてpublishした、という話

xuwei-k.hatenablog.com

github.com

github.com

使い方はREADME見てください。あまり機能がないのと、前回とほぼ使い方は同じなので、何も難しくないと思います。

なぜ今更やろうかと思ったか?というと

  • 自分が把握してる限り、相変わらず完璧な簡単な方法は発明されてないし、Scala 3公式がサポートしたりはしてない、はず?
  • 10行〜20行程度?で済むとはいえ、毎回コピペするの面倒
    • フリーランスになって、各社での大きな仕事の1つにScala 3対応があるが、結局これ大抵必要になる
  • 要素1つの場合だけTuple1にならない問題
    • Scala 2において、case classが要素1の時はunapplyの戻り値型は、 Option[Tuple1[A]] になりません。いくつかのライブラリは、それ前提で作ってあります。しかし、前回書いたshapelessやScala 3のMirrorを使ったテクニックではTuple1になってしまいます。
    • 1要素の場合だけもう、直接field取り出すコードを書けばいい、といえばいいですが、それも地味に面倒になってきたので、しっかり対策を入れました
    • Scala 2ではshapelessを使いつつ、独自にコード生成も駆使しつつ頑張って実装
    • Scala 3では、おそらく transparent inline でも頑張れただろうけど transparent inline よりはmatch typeの方がいいのでは?(何が?)、という気持ちによりmatch typeで実装
    • match typeで型を計算したせいで、内部実装には asInstanceOf が必要になったが、まぁ仕方ない
    • asTuple というメソッド名なのに、要素1の場合にTuple返さないの気持ち悪いけど、まぁヨシ・・・???(別の名前考えるのが面倒だった)

あと、ついでにscala-jsやscala-native対応や、Scala 3、2.13、2.12でcross buildしました。