以下代码打印“* 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)
最佳答案
首先:第二行中的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
的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
强制对流的其余部分进行求值。
关于scala - 为什么我的takeWhile无法与我的Stream一起使用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7923999/