Scala勉強会@東北: The Scala 2.8 Collections API
今日はArrayからでした。
以下メモってた所だけ。
Scala2.7ではArrayはSeqで、コンパイラで色々やってJavaのArrayのふりをしていたけど、Scala2.8では、JavaのArrayとSeqのコンパチブルに変わった。
implicit conversionでArrayからSeqにする(wrappedArray)。
mutable.ArrayOpsというのをラップしてSeqのメソッドを呼べるようにしている。
mutable.ArrayOpsにSeqのサポートが隠れている
コンパチブルになったことにより、SeqのreverseとArrayOpsのreverse、2つ呼ばれる可能性がある。
ArrayOpsの方が優先順位が高い。
PredefにArrayOpsにする implicit def genericArrayOpsがある。
wrapedArrayはLowPriorityImplicitsに定義されている。
2.8からimplicitの優先順位という考えが入った。
//2.7で書けたこの書き方は書けなくなった。 def evenElems[T](xs: Vector[T]): Array[T] = { val arr = new Array[T]((xs.length + 1) / 2) for (i <- 0 until xs.length by 2) arr(i / 2) = xs(i) arr } //error: cannot find class manifest for element type T // val arr = new Array[T]((arr.length + 1) / 2)
ClassManifest渡さないとnew Array[T]がエラー。
//ClassManifestを渡す def evenElems[T](xs: Vector[T])(implicit m: ClassManifest[T]): Array[T] = ...
(implicit m: ClassManifest[T]) の変わりに[T: ClassManifest]と書ける。
// this works def evenElems[T: ClassManifest](xs: Vector[T]): Array[T] = { val arr = new Array[T]((xs.length + 1) / 2) for (i <- 0 until xs.length by 2) arr(i / 2) = xs(i) arr }
StringもArrayと同様な感じでwrappedStringとStringOpsで。
Scala2.7だとRichStringが返ってきていたが、2.8ではStringが返ってくる。
//2.7.7 scala> "abc".reverse res0: scala.runtime.RichString = cba //2.8 scala> "abc".reverse res0: String = cba scala> "abc".toUpperCase res4: java.lang.String = ABC
viewsについて加筆しようと思ったけど、ここ見たらいいと思います。
http://kaitenn.blogspot.com/2010/08/scala-scala-28-collections-api-views.html
RangeはStrictになった。2.7ではlazyだった。
2.7と同じ挙動にしたい場合はviewを使う。
val actors = for (i <- (1 to 10).view) yield actor { ... }
Iteratorでfor式を使うと内部的にはwithFilterに変換される。withFilterはLazy。
for 式中で if を使うと 2.8 では内部的には withFilterに変換される。withFilterはLazy。
2.7 では filter に変換されていて、filterはstrict。