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

时间:2012-03-25 01:04:58

标签: scala stream lazy-evaluation

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

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

如果我们在同一个语句中创建一个Stream,那么在连接之前不会对头部进行评估,这似乎有点令人惊讶。即。

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

#::是右关联的,是ConsWrapper的prepend方法,它是Stream的隐式类。)

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

2 个答案:

答案 0 :(得分: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)

consWrapper的参数是按名称。所以即便如此:

scala> (1 #:: (sys.error("!!"): Stream[Int])).head
res1: Int = 1

答案 1 :(得分:5)

在创建Stream时评估头部。

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