Ответ 1
Хорошо, поэтому, комментируя другие ответы, я подумал, что мог бы также включить мои комментарии в правильный ответ.
Потоки действительно ленивы и будут только вычислять свои элементы по требованию (и вы можете использовать #::
для создания элемента потока по элементу, как ::
для List
). Например, следующее исключение не будет вызывать:
(1/2) #:: (1/0) #:: Stream.empty
Это связано с тем, что при применении #::
хвост передается по имени, чтобы не оценивать его с нетерпением, но только при необходимости (см. ConsWrapper.# ::
, const.apply
и class Cons
в Stream.scala
для более Детали).
С другой стороны, голова передается по значению, а это означает, что ее всегда будут оценивать, независимо от того, что (как упоминалось в Senthil). Это означает, что выполнение следующего действия фактически вызовет исключение ArithmeticException:
(1/0) #:: Stream.empty
Это важно знать о потоках. Однако это не проблема, с которой вы сталкиваетесь.
В вашем случае арифметическое исключение происходит до создания экземпляра только одного потока. При вызове Stream.apply
в lazy val bad = Stream(1/0)
аргумент выполняется с нетерпением, потому что он не объявлен как параметр по имени. Stream.apply
фактически принимает параметр vararg, и они обязательно передаются по значению.
И даже если он был отправлен по имени, ArithmeticException
будет запущен вскоре после этого, потому что, как было сказано ранее, глава Stream всегда оценивается раньше.