为什么我的takeWhile无法使用我的Stream

时间:2011-10-28 00:34:42

标签: scala

以下代码打印“* 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)

1 个答案:

答案 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) 强制评估流的其余部分。