scala 的 for 推导式什么时候会变得懒惰?

发布于 2024-11-28 19:09:16 字数 373 浏览 1 评论 0原文

在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,即使它应该被延迟评估。

In Python, I can do something like this:

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

It will take a while, but the memory use is constant.

The same construct in scala:

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

After a while, I get a java.lang.OutOfMemoryError, even though it should be evaluated lazily.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

过度放纵 2024-12-05 19:09:16

Scala 的 for 理解本质上并不是懒惰的。它是语法糖*,不会改变两个范围的组合将是渴望的事实。

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

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理解无关,而是因为当flatMap 或 map (见下文),您会在相同类型的容器中返回结果。因此,for 理解只会保留您输入的内容的惰性(或缺乏)。


*对于类似的东西:

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

Nothing's inherently lazy about Scala's for-comprehension; it's syntactic sugar* which won't change the fact that the combination of your two ranges will be eager.

If you work with lazy views of your ranges, the result of the comprehension will be lazy too:

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

The laziness here is nothing to do with the for-comprehension, but because when flatMap or map (see below) are called on some type of container, you get back a result in the same type of container. So, the for-comprehension will just preserve the laziness (or lack of) of whatever you put in.


*for something like:

(0 to 10000).flatMap(i => (i+1 to 10000).map(j => (i, j)))
桃气十足 2024-12-05 19:09:16

懒惰不是来自于理解,而是来自于集合本身。您应该研究集合的严格特征。

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

Laziness comes not from the for-comprehension, but from the collection itself. You should look into the strictness characteristics of the collection.

But, for the lazy :-), here's a summary: Iterator and Stream are non-strict, as are selected methods of the view of any collection. So, if you want laziness, be sure to .iterator, .view or .toStream your collection first.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文