~ 2.12
Scala 2.12までは、Iteratorに対するtoSeqはStreamを返すようになっていました。
scala> val xs = Iterator(1, 2, 3).toSeq
xs: Seq[Int] = Stream(1, ?)
2.13 ~
Scala 2.13からは、toSeqがListを返すようになっています。
scala> val xs = Iterator(1, 2, 3).toSeq
xs: Seq[Int] = List(1, 2, 3)
何が問題になるか
元のIteratorのサイズが非常に大きかった場合、処理に時間がかかるか、最悪返ってこなくなります。
scala> val xs = Iterator.continually(1).toSeq
xs: Seq[Int] = Stream(1, ?) ← すぐ返ってくる
scala> val xs = Iterator.continually(1).toSeq
(永遠に返ってこない...)
結論
toSeq
と書いている以上、上記のような実際の具象型に依存した書き方をしないのが賢明と思います。
具象型の特性が必要なら、toList
のように具体的に指定されたメソッドを使用すべきです。
おまけ ~ そもそもScala 2.13ではStreamは非推奨 ~
ちなみにScala 2.13ではscala.collection.immutable.Stream
は非推奨となっており、代わりにscala.collection.immutable.LazyList
を使うことが推奨されています。
Streamとの違いは、tail(先頭以外)だけでなくhead(先頭要素)もlazyになったことです。
Scala 2.13 の LazyList は Stream[CallByNeed[A]]
上記のIteratorをLazyListに変換したい場合、toLazyListというメソッドはないので、LazyList#from
メソッドを使用します。
(19/10/1 追記・修正)
toLazyList
という名のメソッドはないものの、to
メソッドを使えばLazyListを含む統一的なコレクション変換が可能であることをコメント欄で@gakuzzzz様に教えていただきましたので追記します。
@gakuzzzz様のコメントも合わせてご参考にしてください。
scala> val xs = LazyList.from(Iterator.continually(1))
xs: scala.collection.immutable.LazyList[Int] = LazyList(<not computed>)
// toメソッド使用版
scala> val ys = Iterator.continually(1).to(LazyList)
ys: scala.collection.immutable.LazyList[Int] = LazyList(<not computed>)
Streamと同様、結果がすぐ返ってきました。
ちなみにStreamにも同じようにStream#from
メソッドがありますが(非推奨)、こちらは先頭要素のみ評価されているのがわかります。1
scala> val xs = Stream.from(Iterator.continually(1))
xs: scala.collection.immutable.Stream[Int] = Stream(1, <not computed>)
最後までお読み頂きありがとうございました。 質問や不備についてはコメント欄か[Twitter](https://twitter.com/ka2_kamaboko)までお願いします。
-
Streamに関しては
toStream
メソッドもありますが、どっちにしろ非推奨なので今後使用することはないと思います。 ↩