As others have already mentioned, #::
is defined on scala.collection.immutable.Stream.ConsWrapper
. I just wanted to take a minute to elaborate on why that is.
In general, to call an operator on an object, that object needs to exist. However, the idea with a Stream is the tail of the stream is not evaluated until it needs to be. So consider the following stream:
def fibs(a:Int,b:Int):Stream[Int] = a #:: fibs(b,a+b)
Ordinarily, we would need to evaluate the recursive fibs
call so that we could call the #::
operator on it. This would lead to runaway recursion. This is NOT what we want. What we want is for the reciever to be a by-name Stream
. Hence the ConsWrapper
:
The constructor for ConsWrapper
is class ConsWrapper[T](tail: => Stream[T])
taking a by-name Stream
, and it's created through an implicit conversion Stream.consWrapper[T](stream: => Stream[T])
, which also takes a by-name Stream
.
Hence, we have performed an implicit conversion on the result of a function that has not yet been called, and we have mimiced the effect of calling #::
with a by-name this
reference.