通常,如果您创建一个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之前,这怎么不评价它的头?在我们从结果流中获取值之前,堆尾流(或缺点单元格)是否存在于堆中?但如果是这样,我们如何在一个不存在的对象上调用#::
方法呢?
答案 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)
。