以下代码打印*1".令人困惑的是,如果我删除评论,它会返回*4",这正是我所期待的
The following code prints "*1". What's mystifying is if I remove the comment it returns "*4" which is what I was expecting
var max = 0 lazy val list: Stream[Int] = 1 #:: Stream.from(2) list.takeWhile { x => max = x x < 4 }//.foreach(println) println("*" + max) 推荐答案首先:第二行中的 lazy 没有做任何事情——你可以删除它并获得相同的结果.
First of all: the lazy in your second line isn't doing anything—you can remove it and get the same result.
更重要的是:takeWhile实际上是懒惰的,因为它只返回另一个Stream,并且没有超过那个流的头部评估直到需要.考虑以下几点:
More importantly: takeWhile is actually lazy, in that it just returns another Stream, and nothing past the head of that stream will be evaluated until it's needed. Consider the following:
val s = Stream.from(1).takeWhile(_ > 0)你和我都知道 s 将是一个无限流,但如果我们启动 REPL 并输入它,很高兴评估它:
You and I know that s is going to be an infinite stream, but if we fire up the REPL and type this in, it's perfectly happy to evaluate it:
scala> val s = Stream.from(1).takeWhile(_ > 0) s: scala.collection.immutable.Stream[Int] = Stream(1, ?)在您的示例中发生了同样的事情:您传递给 takeWhile 的 (Int) ⇒ Boolean 不会被提供给超出流的头部,直到您的 foreach 之类的东西使之成为必需.
The same thing is happening in your example: the (Int) ⇒ Boolean that you've passed to takeWhile isn't going to get fed any elements beyond the head of the stream, until something like your foreach makes that necessary.
通过在 takeWhile 谓词中添加类似 println 之类的内容,您可以更显着地看到这一点:
You can see this even more dramatically by adding something like a println inside of the takeWhile predicate:
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 强制对流的其余部分进行评估.
Clearly the predicate only gets called for the head of the stream, until we force the evaluation of the rest of the stream by calling toList.
更多推荐
为什么我的 takeWhile 无法与我的 Stream 一起使用
发布评论