型パラメーターを使った Array.fill とかをしたい場合
環境
scala 2.9.1.final
まずは REPL でやってみる
scala> def fill[T](v: T) = List.fill(10)(v) fill: [T](v: T)List[T] scala> fill("hoge") res0: List[java.lang.String] = List(hoge, hoge, hoge, hoge, hoge, hoge, hoge, hoge, hoge, hoge) scala> def fill[T](v: T) = Array.fill(10)(v) <console>:7: error: could not find implicit value for evidence parameter of type scala.reflect.ClassManifest[T] def fill[T](v: T) = Array.fill(10)(v)
????????????
なんぞこれwww
List.fill は動くのに Array.fill は動きません!!!!
List.fill と Array.fill は引数が違うらしい
http://www.scala-lang.org/api/current/index.html#scala.collection.immutable.List$
http://www.scala-lang.org/api/current/index.html#scala.Array$
ドキュメントみりゃ分かるんですが
List は fill [A] (n: Int)(elem: ⇒ A): List[A] となってるのに対して
Array は fill [T] (n: Int)(elem: ⇒ T)(implicit arg0: ClassManifest[T]): Array[T] になってるっぽいです。
なんでこうなってるのかは知りませんが、こうなってるから動かないのは分かりました。
というわけで ClassManifest (型情報的なもの)を渡してあげましょう。
ClassManifest 結構大事だと思ってるので、くどいですが最初は一つずつやってみます。
またまた手前味噌でさーせんが ClassManifest の基本的な部分はこちらをどうぞorz
つhttp://wiki.livedoor.jp/alphaneet/d/scala%3a%3a%b7%bf%a5%d1%a5%e9%a5%e1%a1%bc%a5%bf%a1%bc
1: ClassManifest を手渡しでやってみる
引き続き REPL で
scala> def fill[T](v: T, cm: ClassManifest[T]) = Array.fill(10)(v)(cm) fill: [T](v: T, cm: ClassManifest[T])Array[T] scala> fill(12345, classManifest[Int]) res4: Array[Int] = Array(12345, 12345, 12345, 12345, 12345, 12345, 12345, 12345, 12345, 12345)
出来ました。でも、もの凄い冗長ですよね。
2: implicit を使って省略してみる。
scala> def fill[T](v: T)(implicit cm: ClassManifest[T]) = Array.fill(10)(v)(cm) fill: [T](v: T)(implicit cm: ClassManifest[T])Array[T] scala> fill("moke") res5: Array[java.lang.String] = Array(moke, moke, moke, moke, moke, moke, moke, moke, moke, moke)
呼び出し方がすっきりしました。
ちなみに Array.fill(10)(v)(cm) のところは Array.fill(10)(v) でも動きます。
実はまださらに省略することが出来ます。
3: context bound を使ってみる
scala> def fill[T: ClassManifest](v: T) = Array.fill(10)(v) fill: [T](v: T)(implicit evidence$1: ClassManifest[T])Array[T] scala> fill("oppai") res6: Array[java.lang.String] = Array(oppai, oppai, oppai, oppai, oppai, oppai, oppai, oppai, oppai, oppai)
凄いすっきりしましたね。
まとめ
1、2、3 はそれぞれやってること自体は大体一緒です。
今回は Array(標準API) なんでどの方法使ってもいいと思いますが、自分でライブラリ作った場合どの方法で実装するのがいいのかなーと考えますと。。。
1 は論外として 2 と 3 どっちを選ぶか悩みますね。
3 は確かにすっきりしててイケメンなんですが、省略しすぎて他の人が見た時混乱するかもしれません。
個人(趣味)開発の場合はどっちでもいいと思いますが(むしろ 3 カコイイ)
チーム開発の場合は 2 ぐらいで妥協しておくべきかなーと思いました。まる。