I know streams are supposed to be lazily evaluated sequences in Scala, but I think I am suffering from some sort of fundamental misunderstanding because they seem to be more eager than I would have expected.
In this example:
val initial = Stream(1)
lazy val bad = Stream(1/0)
println((initial ++ bad) take 1)
I get a java.lang.ArithmeticException, which seems to be cause by zero division. I would expect that bad would never get evaluated since I only asked for one element from the stream. What’s wrong?
OK, so after commenting other answers, I figured I could as well turn my comments into a proper answer.
Streams are indeed lazy, and will only compute their elements on demand (and you can use
#::to construct a stream element by element, much like::forList). By example, the following will not throw any exception:This is because when applying
#::, the tail is passed by name so as to not evaluate it eagerly, but only when needed (seeConsWrapper.# ::,const.applyand classConsinStream.scalafor more details).On the other hand, the head is passed by value, which means that it will always be eagerly evaluated, no matter what (as mentioned by Senthil). This means that doing the following will actually throw a ArithmeticException:
It is a gotcha worth knowing about streams. However, this is not the issue you are facing.
In your case, the arithmetic exception happens before even instantiating a single Stream. When calling
Stream.applyinlazy val bad = Stream(1/0), the argument is eagerly executed because it is not declared as a by name parameter.Stream.applyactually takes a vararg parameter, and those are necessarily passed by value.And even if it was passed by name, the
ArithmeticExceptionwould be triggered shortly after, because as said earlier the head of a Stream is always early evaluated.