什么时候对Stream的头部进行评估?

Lui*_*hys 10 scala stream lazy-evaluation

通常,如果您创建一个Stream对象,则会热切地评估头部:

scala> Stream( {println("evaluating 1"); 1} , 2, 3)
evaluating 1
res63: scala.collection.immutable.Stream[Int] = Stream(1, ?)
Run Code Online (Sandbox Code Playgroud)

如果我们创建一个我们在同一语句中添加的Stream,那么在连接之前不会对头进行求值似乎有点令人惊讶.即

scala> 0 #:: Stream( {println("evaluating 1"); 1} , 2, 3)
res65: scala.collection.immutable.Stream[Int] = Stream(0, ?)
Run Code Online (Sandbox Code Playgroud)

(#::是右关联的,是prepend方法ConsWrapper,它是一个隐式类Stream.)

在预先设定0之前,这怎么不评价它的头?在我们从结果流中获取值之前,堆尾流(或缺点单元格)是否存在于堆中?但如果是这样,我们如何#::在一个不存在的对象上调用该方法呢?

ret*_*nym 7

-Xprint:typer 是你的朋友,任何时候你想要准确理解一些代码是如何评估或推断类型的.

scala -Xprint:typer -e '0 #:: Stream( {println("evaluating 1"); 1} , 2, 3)'

val x$1: Int = 0;
Stream.consWrapper[Int](Stream.apply[Int]({
  println("evaluating 1");
  1
}, 2, 3)).#::(x$1)
Run Code Online (Sandbox Code Playgroud)

参数consWrapper是按名称.所以即使这样工作:

scala> (1 #:: (sys.error("!!"): Stream[Int])).head
res1: Int = 1
Run Code Online (Sandbox Code Playgroud)


Jen*_*der 5

在创建Stream时评估头部.

但是在第二个示例中,您没有传递Streem作为#::传递by name参数的第二个参数,即Stream( {println("evaluating 1"); 1} , 2, 3)根本不评估完整表达式.