首先:在你的第二个行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, ?)
您的示例中发生了同样的事情:您传递给takeWhile
的(Int) ⇒ Boolean
将不会获得流头之外的任何元素,直到像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
的其余部分流。