Scala 为什么takeWhile无法与流一起工作

Scala 为什么takeWhile无法与流一起工作,scala,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) var max=0 lazy val list:Stream[Int]=1#:::Stream.from(2)

以下代码打印“*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)
var max=0
lazy val list:Stream[Int]=1#:::Stream.from(2)
list.takeWhile{
x=>
最大值=x
x<4
}//.foreach(println)
println(“*”+最大值)

首先:第二行中的
懒惰的
没有做任何事情,您可以删除它并获得相同的结果

更重要的是:
takeWhile
实际上是懒惰的,因为它只返回另一个
,并且在需要之前不会对超过该流头部的任何内容进行评估。考虑以下事项:

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)⇒ 传递给
takeWhile
的Boolean
将不会得到流头以外的任何元素,直到像您的
foreach
这样的东西成为必要

通过在
takeWhile
谓词中添加类似于
println
的内容,您可以更显著地看到这一点:

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)
scala>vals=Stream.from(1).takeWhile{x=>println(“检查:+x);x<4}
核对:1
s:scala.collection.immutable.Stream[Int]=流(1,?)
scala>val l=s.toList
支票:2
支票:3
支票:4
l:List[Int]=List(1,2,3)
显然,谓词只会被调用为流的头部,直到我们通过调用
toList
强制计算流的其余部分