15

在 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,即使它应该被懒惰地评估。

4

2 回答 2

25

Scala 的理解力没有什么天生懒惰的。它是语法糖*,它不会改变您的两个范围的组合将是渴望的事实。

如果您使用view您的范围的 lazy ,则理解的结果也将是惰性的:

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

这里的懒惰与理解无关,但因为当flatMapmap(见下文)在某种类型的容器上调用时,您会在相同类型的容器中返回结果。因此,理解只会保留您输入的任何内容的懒惰(或缺乏)。


*对于类似的东西:

(0 to 10000).flatMap(i => (i+1 to 10000).map(j => (i, j)))
于 2011-08-09T12:25:55.037 回答
13

懒惰不是来自于理解,而是来自于收藏本身。您应该查看集合的严格性特征。

但是,对于懒惰的 :-),这里有一个总结:Iterator并且Stream是非严格的view,任何集合的选定方法也是如此。所以,如果你想偷懒,一定要先.iterator.view或者.toStream你的收藏。

于 2011-08-09T12:43:03.113 回答