流的头部究竟何时被评估



通常,如果你创建一个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上的前置方法,是Stream的隐式类。

这如何在前缀 0 之前不计算其头部?在我们从生成的流中获取值之前,尾流(或 cons 单元格(是否不存在堆上?但如果是这样,我们如何在尚不存在的对象上调用 #:: 方法?

-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

创建流的那一刻评估头部。

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

相关内容

  • 没有找到相关文章

最新更新