How does this work in Scala?

This echoes stdin to stdout:

collection.Iterator
  .continually(io.StdIn.readLine()) // Is this the same as continually(io.StdIn.readLine)?
  .foreach { line =>
    println(s"got: $line")
  }

But I’m surprised it works. Why isn’t io.StdIn.readLine() evaluated when the iterator is created? i.e., why doesn’t the above code behave like below:

val s = io.StdIn.readLine()
collection.Iterator
  .continually(s)
  .foreach { line =>
    println(s"got: $line")
  }

Note the signature of continually():

def continually[A](elem: => A): Iterator[A]

In particular, note that => A. That means that it is a “by-name” parameter – one that is re-evaluated every time the parameter is accessed inside the function.

If the type of elem was just A, then it would work as you expect. But by-name params exist specifically so they can be dynamic like this, with the parameter evaluated any number of times (including zero), depending on how the function works.

4 Likes