もくじ
- もくじ
- 自己紹介
- implicitとは
- なぜ implicit と呼ばれるか
- sortedは何が起こっているのか
- Enrich my Library パターン
- sortedのOrdering[Int]は?どこに定義されている
- 暗黙の値をスコープに加える代表的な方法
- MapとContramap
- 感想
自己紹介
implicitとは
Scalaには大きく分けて2つのimplicitがある
Implicit parameter(暗黙の引数) Implicit conversion(暗黙の変換)
Implicit conversionはある意味implicit parameterの一種なのだが、わかりやすくするために分けてある。
implicit parameter とは
Scalaの標準ライブラリのSeqのsortedで使われてる。
Sortedはソートするメソッド
Seq(2, 1, 3).sorted // -> Seq(1, 2,3)
標準のソートの順番がimplicitで定義されている
implicit conversion
暗黙の型変換
例えばjavaのListとScalaのListに変換するのに暗黙の型変換が使われている。
val jlist: Javaのリスト = Sew(scalaのリスト)
なぜ implicit と呼ばれるか
何が起きているのかコード上からわからない(わかりづらい、ので難しい)
暗黙のスコープというものがある
ということで少しなれるのにハードルがある。
「暗黙の値」が他の暗黙の値を使っていたり、関数の引数に暗黙の値を使っていたり、などで複雑で難しい
このセッションはこの暗黙にどう向き合っていったらいいかを考える。
sortedは何が起こっているのか
Seq(2, 1, 3).sorted
について
scalacでオプションに-Xprint:typer をつけると、自分の書いた式が同評価されているかわかる。sortedには何も引数は私絵いなくても、勝手に何か引数が渡されている。
scala -Xprint:typer
で実際に何が呼ばれているかわかる
プロジェクトではどうするか
プロジェクトだと typer つかうとめっちゃ色々出てきてやばい。IntelliJのimplicitまわりの機能は非常に良い。
IntelliJ の Ctrl + Shift + P
にバインドされていると、implicit parameter が定義されているところに飛べる。(Community Editionでいける)
// MEMO: scalaのdiってimplicit parameter使えるのだろうか
ある暗黙の値を使って別の暗黙の値を定義している場合などは?
同じく Ctrl + Shift + P
、トグルを開くとさらにその先の暗黙の値が見られる。
Enrich my Library パターン
Scalaにおいて暗黙の型変換を使って実装されるパターン
「私のライブラリをリッチにします」
// TODO: 話が早くてどういうパターンかわからなかったのでぐぐる
Java convertersの例(Enrich my Library じゃない例?)
例えば、JavaのListの引数を渡すところにScalaのListを渡すと勝手にJavaのリストに変換される。勝手に変換されていることに気づきにくいため、バグの温床になる可能性がある。(わかる)
たとえば、自分implicitでasJava関数を定義する。以下のようにScalaのリストとJavaのリストを変換できるようにする。
val list:java.util.List[Int] = List(1, 2, 3).asJava
この場合、コードジャンプで asJava の実装もとに飛べる。
scala.collectionJavaConvertes (deprecated)を使う
Import scala.collectionJavaConvertes val list:java.util.List[Int] = List(1, 2, 3)
暗黙の型変換になった(asJavaがなくなった)。暗黙の型変換が怒っていることに気づかないしコードジャンプも厳しい。
ので、Enrich my Library パターンを使おう!
sortedのOrdering[Int]は?どこに定義されている
// MEMO: 早くてメモしきれなかったので資料を見る
暗黙の値をスコープに加える代表的な方法
明示的に暗黙の値をimportするか、スコープに直接定義する。
なんの型のコンパニオンオブジェクトに定義したらいいかが問題。
どんなコンパニオンオブジェクトに定義したらいいのか
Scalaのドキュメント読んでもピンとこないので説明します。
Parameterized Type Super Type Package Object
などなど
Implicit classはimportすることでimplicitが定義されるので余計な事故を防げる。
例えば Ordering[User] を定義する
List[User]のsortedのデフォルトを定義するやりかた
object User の中に定義する
Odering[User] を定義する必要がある。Ordering.by を使う
Ordering.by(.id) とか Ordering.by(.name) とか
MapとContramap
Readsのはmapという名前で定義 Writesを定義する場合はcontramapという名前で定義
共変・半変の説明は省略
PlayのJsonのやつのReadsとかWritesとかがそれかな
感想
内容は面白かったけどもりだくさんで少し説明が早い><
// TODO: スライド公開されたら見たほうがいい。あとで公開するとのこと。