Scala2.8のMapでapplyとかimplicitとか
備忘録的メモ。
Map(1->2,3->4)を丁寧に?読み解く。自分理解なので突っ込み歓迎。
//こうはできない scala> new Map(1->2,3->4) <console>:7: error: trait Map is abstract; cannot be instantiated new Map(1->2,3->4) ^
これはなんなのか。
//第一段階 scala> Map.apply(1->2,3->4) res24: scala.collection.immutable.Map[Int,Int] = Map(1 -> 2, 3 -> 4)
こうなる。object MapがextendsしているMapFactoryのapplyメソッドを呼び出す。
applyメソッドの引数が可変長引数になっているため、複数つっこめるのは判断できるが、applyメソッドの引数はtupleのpairとなっている。
が、渡しているのは1->2などとなっている。
この1->2という書き方は、(1).->(2)だが、Intには->というメソッドは存在しない。
ここで暗黙のレシーバー変換が登場する。
型エラーを検出し、Intから->をもっている型への変換をさがしにいく。
この場合、Predefにあるany2ArrowAssocを探しだし*1、1:IntはArrowAssocクラスに型変換され、ArrowAssocの->メソッドが呼び出される。
scala> Map.apply(any2ArrowAssoc(1).->(2),any2ArrowAssoc(3).->(4)) res29: scala.collection.immutable.Map[Int,Int] = Map(1 -> 2, 3 -> 4) //こう。 scala> Map.apply(new ArrowAssoc(1).->(2),new ArrowAssoc(3).->(4)) res32: scala.collection.immutable.Map[Int,Int] = Map(1 -> 2, 3 -> 4)
ArrowAssocの->メソッドはTupple2を返すので・・
//こうなる scala> Map.apply(Tuple2(1,2),Tuple2(3,4)) res35: scala.collection.immutable.Map[Int,Int] = Map(1 -> 2, 3 -> 4) //Tuple2(1,2)もapplyだけど省略 scala> Map.apply((1,2),(3,4)) res36: scala.collection.immutable.Map[Int,Int] = Map(1 -> 2, 3 -> 4)
*1:[A]はAny