【问题标题】:Scala Stream confusionScala Stream混淆
【发布时间】:2011-12-15 21:14:03
【问题描述】:

跑步:

lazy val s: Stream[Int] = 1 #:: 2 #:: {val x = s.tail.map(_+1); println("> " + x.head); x}
s.take(5).toList

我希望:

> List(2, 3)
> List(2, 3, 4)
List(1, 2, 3, 4, 5)

我得到:

> 3
List(1, 2, 3, 4, 5)

你能给我解释一下吗?

【问题讨论】:

  • 您为什么希望x.head 返回一个列表?
  • 让我感到困惑的是,你到底为什么要在惰性 val 的定义中添加 println
  • @Dan:我想知道表达式执行的时间和频率(以及执行时的各种值)。

标签: scala recursion stream tail


【解决方案1】:

您得到Int 而不是List 的原因是s 是一个整数流,因此它包含整数,而不是列表。

你得到 3 的原因是 (1,2,3,4,5,...) 的尾部(即s)是 (2,3,4,5,...) 和如果你在上面映射 +1,你会得到 (3,4,5,6,7,...) 并且它的头部是 3。

只打印一个整数的原因是表达式只计算一次以获得尾部的流。之后,仅评估 s.tail.map(_+1) 返回的流(不包含任何打印语句)。

【讨论】:

  • 考虑这一点:val s: Stream[Int] = 1 #:: 2 #:: {val x = s.tail.map(1+); x take 10 print; x} 将打印 3333... 并下降,所以 x 似乎是一个三连串,而不是 3、4、5,......但这没有任何意义,因为那么s 应该是Stream(1,2,3,3,3,...)。我很困惑,有什么建议,我可以在哪里阅读更多关于流的信息?
  • @4e6:在生成流的表达式中消耗的流元素多于已生成的元素,将导致无限递归(最终会炸毁堆栈)。你得到这么多 3 的原因不是流包含那么多 3(如果有的话,它们会用逗号分隔),而是 print 语句执行了这么多次(因为逻辑递归循环并到达打印语句一次又一次……)。
  • @4e6 考虑一下您写的内容:要计算第三个数字,它需要打印前 10 个数字。但是如果它还没有计算出来,它怎么能打印第三个数字呢?那就是你得到一个错误。
  • sepp2k,@DanielC.Sobral,我想我现在明白了。非常感谢和 +1 :)
  • 是否正确地说,由于流使用了记忆,所以 println(x) 的评估结果被存储,因此不再评估表达式?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-03-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-09-11
相关资源
最近更新 更多