Streams
Scala's streams are lazy lists, an infinite sequence of elements. For example, just like we zip two lists together, we could zip two streams too:
scala> def zip(p: Stream[Int], q: Stream[Int]): Stream[(Int, Int)] =
| (p.head, q.head) #:: zip(p.tail, q.tail)
zip: (p: Stream[Int], q: Stream[Int])Stream[(Int, Int)]
scala> val r = zip(Stream.from(9), Stream.from(10))
r: Stream[(Int, Int)] = Stream((9,10), ?)
As you can see, the type of r variable is another stream. Also, the stream has a head element, a pair (9,10), and a function (also called a thunk). The function (in this case, zip) is called to produce successive elements.
As you can see, the tail is a question, meaning it is not yet computed; therefore, it is not yet known.
Why are streams called lazy? Note the definition of zip, which is defined recursively. There is no condition related to termination; the calls just recur. A recursive call is not evaluated right away but only when it is needed.
The idea is to force...