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。