以下代码打印“* 1”。令人费解的是,如果我删除评论,它会返回“* 4”,这正是我所期待的
var max = 0
lazy val list: Stream[Int] = 1 #:: Stream.from(2)
list.takeWhile {
x =>
max = x
x < 4
}//.foreach(println)
println("*" + max)
答案 0 :(得分:20)
首先:第二行中的lazy
没有做任何事情 - 您可以删除它并获得相同的结果。
更重要的是:takeWhile
实际上懒惰,因为它只返回另一个Stream
,并且在该需要之前,将评估该流的头部之外的任何内容。请考虑以下事项:
val s = Stream.from(1).takeWhile(_ > 0)
你和我知道s
将是一个无限的流,但是如果我们启动REPL并输入它,那么很高兴评估它:
scala> val s = Stream.from(1).takeWhile(_ > 0)
s: scala.collection.immutable.Stream[Int] = Stream(1, ?)
在您的示例中也发生了同样的事情:您传递给(Int) ⇒ Boolean
的{{1}}不会获得超出流的头部的任何元素,直到您的{takeWhile
{1}}做到了这一点。
通过在foreach
谓词中添加println
之类的内容,您可以更加明显地看到这一点:
takeWhile
显然,仅在流的头部调用谓词,直到我们通过调用scala> val s = Stream.from(1).takeWhile { x => println("Checking: " + x); x < 4 }
Checking: 1
s: scala.collection.immutable.Stream[Int] = Stream(1, ?)
scala> val l = s.toList
Checking: 2
Checking: 3
Checking: 4
l: List[Int] = List(1, 2, 3)
强制评估流的其余部分。