Когда именно оценивается глава потока? - PullRequest
10 голосов
/ 25 марта 2012

Обычно, если вы создаете объект 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, ?)

(#:: является ассоциативным справа и является методом prepend для ConsWrapper, который является неявным классом Stream.)

Как это не оценивает свою голову перед добавлением 0? Неужели хвостовой поток (или ячейка минусов) не существует в куче, пока мы не примем значения из результирующего потока? Но если так, как мы вызываем метод #:: для объекта, который еще не существует?

Ответы [ 2 ]

7 голосов
/ 25 марта 2012

-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
5 голосов
/ 25 марта 2012

Голова оценивается в момент создания потока.

Но во втором примере вы не передаете Streem в качестве второго аргумента #::, вы передаете параметр по имени, то есть полное выражение Stream( {println("evaluating 1"); 1} , 2, 3) вообще не оценивается.

...