首先:lazy
第二行中的 没有执行任何操作 - 您可以将其删除并获得相同的结果。
更重要的是:takeWhile
is actually懒惰,因为它只是返回另一个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
你已经传递给takeWhile
不会得到流头部之外的任何元素,直到像你的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)
显然,谓词仅针对流的头部调用,直到我们通过调用强制评估流的其余部分toList
.