【问题标题】:When are scala's for-comprehensions lazy?scala 的理解力什么时候是懒惰的?
【发布时间】:2011-08-09 12:18:52
【问题描述】:

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

【问题讨论】:

    标签: scala lazy-evaluation for-comprehension


    【解决方案1】:

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

    如果你使用你的范围的惰性views,那么理解的结果也将是惰性的:

    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)))
    

    【讨论】:

    • "something like",但后一个表达式似乎返回 100020001 个元素,而不是 50005000。威士忌探戈狐步舞?
    • @Malvolio 感谢您的关注! j 应该来自 i+1 to 10000,而不是 1 to 10000。现已修复。
    • 哦。我应该注意到解决方案,而不仅仅是问题。我盯着地图函数,忽略了参数..
    • Int.to(Int) 在 2.7 中不是懒惰的吗?
    【解决方案2】:

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-01-21
      • 1970-01-01
      • 2013-03-15
      • 1970-01-01
      • 2015-09-06
      • 2019-10-15
      • 2012-11-04
      • 2011-11-21
      相关资源
      最近更新 更多