メモ
Scala勉強中
Collectionについていろいろ試してみた。
結論もなければ整理もしてないので悪しからず。。
MapやListに関数を入れられる
scala> val m = Map("func" -> {i:Int=>i*3}) m: scala.collection.immutable.Map[java.lang.String,Int => Int] = Map(func -> <function1>)
でもgetやgetOrElseで取り出すと
scala> m.getOrElse("func", None)
res71: ScalaObject = <function1>
上手く実行できない scala> m.getOrElse("func", None)(3) <console>:9: error: ScalaObject does not take parameters m.getOrElse("func", None)(3) ^
どうもOptionで包まれて返ってくる値を上手く取り出すにはMatchを使うのがいいっぽい。
scala> m.get("func") match{ | case Some(f) => f(2) | case None => "none" | } res68: Any = 6
こうすると中身を上手く取り出せるが、Any, Some, Optionの意味がまだ分かってない。
ごちゃ混ぜのMapも書ける
scala> val m = Map("func" -> {i:Int=>i*2}, "name" -> "ikeda", 3 -> "number", ("localhost", 9000) -> "Play") m: scala.collection.immutable.Map[Any,java.lang.Object] = Map(func -> <function1>, name -> ikeda, 3 -> number, (localhost,9000) -> Play)
下記のように書いたら取り出せるかとおもいきやコンパイルエラー。
scala> m.foreach { | case (function1, f) => f(3) | case Some(v) => v | case ((String,Int),name) => name | case None => "none" | }
getOrElseで取り出しても、Any,Objectになっちゃうから、関数として取り出せないっぽい?
scala> m.getOrElse("func",0) res3: Any = <function1> scala> val f = m.getOrElse("func",0) f: Any = <function1> scala> f res4: Any = <function1> scala> f(3) <console>:10: error: Any does not take parameters f(3) ^ scala> val f:function1 = m.getOrElse("func", {}) <console>:8: error: not found: type function1 val f:function1 = m.getOrElse("func", {}) ^ scala> val f:Function1 = m.getOrElse("func", {}) <console>:8: error: trait Function1 takes type parameters val f:Function1 = m.getOrElse("func", {}) ^ scala> val f:Function1[function1] = m.getOrElse("func", {}) <console>:8: error: wrong number of type arguments for Function1, should be 2 val f:Function1[function1] = m.getOrElse("func", {}) ^ scala> val f:Function1[Int,Int] = m.getOrElse("func", {}) <console>:8: error: type mismatch; found : Unit required: Int => Int val f:Function1[Int,Int] = m.getOrElse("func", {}) ^ scala> val f:Function1[Int,Int] = m.getOrElse("func", None) <console>:8: error: type mismatch; found : None.type (with underlying type object None) required: Int => Int val f:Function1[Int,Int] = m.getOrElse("func", None) ^ scala> val f:Function1[Int,Int] = m.getOrElse("func", {i:Int=>1}) <console>:8: error: type mismatch; found : java.lang.Object required: Int => Int val f:Function1[Int,Int] = m.getOrElse("func", {i:Int=>1}) ^ scala> val f:Function1[Int,Int] = m.getOrElse[Function1[Int,Int]]("func", {i:Int=>1}) <console>:8: error: type arguments [Int => Int] do not conform to method getOrElse's type parameter bounds [B1 >: java.lang.Object] val f:Function1[Int,Int] = m.getOrElse[Function1[Int,Int]]("func", {i:Int=>1}) ^ scala> m res6: scala.collection.immutable.Map[Any,java.lang.Object] = Map(func -> <function1>, name -> ikeda, 3 -> number, (localhost,9000) -> Play) scala> val f:Function1[Int,Int] = m.getOrElse[Function1[Int,Int]]("func", {i:Int=>1}) <console>:8: error: type arguments [Int => Int] do not conform to method getOrElse's type parameter bounds [B1 >: java.lang.Object] val f:Function1[Int,Int] = m.getOrElse[Function1[Int,Int]]("func", {i:Int=>1})
map関数
scala> val number = List(1,2,3) number: List[Int] = List(1, 2, 3) scala> number.map( (i:Int) => i*2 ) res7: List[Int] = List(2, 4, 6)
これはOK
こうも書ける
scala> val f = (i:Int) => i*2 f: Int => Int = <function1> scala> number.map(f) res9: List[Int] = List(2, 4, 6)
こうでも一緒
scala> number.map(f(_)) res12: List[Int] = List(2, 4, 6)
でも、これはNG
scala> number.map(f _) <console>:10: error: type mismatch; found : () => Int => Int required: Int => ? number.map(f _)
defで宣言してこうも書ける
scala> def timesTwo(i:Int) = i*2 timesTwo: (i: Int)Int scala> number.map(timesTwo _) res11: List[Int] = List(2, 4, 6)
これもOK
scala> number.map(timesTwo(_)) res13: List[Int] = List(2, 4, 6)
defで宣言した時と、無名関数として作った場合とで挙動が違うっぽい。
引数の渡され方の問題?
これ出来るの結構便利
scala> val (x,y) = number.partition(_>2) x: List[Int] = List(3) y: List[Int] = List(1, 2) scala> x res23: List[Int] = List(3) scala> y res24: List[Int] = List(1, 2)
filterやmapにはコードブロックが渡せて、中でCase書ける。なんでかはわからんが。。
scala> val extensions = Map("steve" -> 100, "bob" -> 101, "joe" -> 201) extensions: scala.collection.immutable.Map[java.lang.String,Int] = Map(steve -> 100, bob -> 101, joe -> 201)
こんなふうにも書けるし。
scala> extensions.filter( (name: (String,Int)) => name._2 < 200 ) res18: scala.collection.immutable.Map[java.lang.String,Int] = Map(steve -> 100, bob -> 101)
これはダメだけど、
scala> extensions.filter( case (name, ex) => ex < 200 ) <console>:1: error: illegal start of simple expression extensions.filter( case (name, ex) => ex < 200 ) ^
こうすればOK
scala> extensions.filter({ case (name, ex) => ex < 200 }) res19: scala.collection.immutable.Map[java.lang.String,Int] = Map(steve -> 100, bob -> 101)
こうすればmapもできる。
scala> extensions.map({ case(name,ex) => ex*2 } ) res20: scala.collection.immutable.Iterable[Int] = List(200, 202, 402)
mapしたあとタプルで返せば再びMapになる。
scala> extensions.map({ case(name,ex) => name->ex*2 } ) res21: scala.collection.immutable.Map[java.lang.String,Int] = Map(steve -> 200, bob -> 202, joe -> 402)