什么时候斯卡拉的理解是懒惰的?

时间:2011-08-09 12:18:53

标签: scala lazy-evaluation for-comprehension

在Python中,我可以这样做:

lazy = ((i,j) for i in range(0,10000) for j in range(0,10000))
sum((1 for i in lazy))

这需要一段时间,但内存使用是不变的。

scala中的相同构造:

(for(i<-0 to 10000; j<-i+1 to 10000) yield (i,j)).count((a:(Int,Int)) => true)

过了一会儿,我得到一个java.lang.OutOfMemoryError,即使它应该懒得评估。

2 个答案:

答案 0 :(得分:22)

对于Scala的理解,没有任何内在的懒惰;它的语法糖*不会改变你的两个范围的组合将是渴望的事实。

如果你使用范围的懒惰view,理解的结果也会很懒:

scala> for(i<-(0 to 10000).view; j<-(i+1 to 10000).view) yield (i,j)
res0: scala.collection.SeqView[(Int, Int),Seq[_]] = SeqViewN(...)

scala> res0.count((a: (Int, Int)) => true)
res1: Int = 50005000

这里的懒惰与for-comprehension无关,但是因为在某种类型的容器上调用flatMapmap(见下文)时,你会得到同样的结果容器类型。因此,for-comprehension将保留你所投入的任何懒惰(或缺乏)。


*类似于:

(0 to 10000).flatMap(i => (i+1 to 10000).map(j => (i, j)))

答案 1 :(得分:12)

懒惰不是来自理解,而是来自收藏本身。你应该研究一下这个集合的严格特征。

但是,对于懒惰的:-),这里有一个摘要:IteratorStream是非严格的,任何集合的view的选定方法也是如此。因此,如果您想要懒惰,请务必先.iterator.view.toStream收藏。