Does anyone have any idea/explanation why REPL is stuck during evaluation of last expression? The weird thing is that it does not throw any exception or anything, just nothing happens.
Welcome to Scala version 2.11.6 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_40).
scala> val empty = Seq.empty[Int].iterator
empty: Iterator[Int] = empty iterator
scala> val emptyInfiniteIterator = Iterator.continually(empty).flatten
Thanks in advance for any explanation.
Here is what happens. When you define iterator in Scala REPL, some information about that iterator is printed, whether it's empty or not in particular:
scala> Iterator.continually(List(1)).flatten
res1: Iterator[Int] = non-empty iterator
This information is returned by toString
method of Iterator
, which is defined like this:
override def toString = (if (hasNext) "non-empty" else "empty")+" iterator"
Basically, hasNext
is called on newly created iterator. Now let's see what hasNext
does in your case (scala.collection.TraversableOnce.FlattenOps#flatten
):
class FlattenOps[A](travs: TraversableOnce[TraversableOnce[A]]) {
def flatten: Iterator[A] = new AbstractIterator[A] {
val its = travs.toIterator
private var it: Iterator[A] = Iterator.empty
def hasNext: Boolean = it.hasNext || its.hasNext && { it = its.next().toIterator; hasNext }
def next(): A = if (hasNext) it.next() else Iterator.empty.next()
}
}
Aha! hasNext
recursively traverses the iterator trying to find either an end or single non-empty element. Which, in your case, never happens, as you have infinite iterator of empty elements. So, you have infinite loop which is triggered by REPL. You don't get StackOverflow
, because tail recursion is used and in scala it's transpiled to while loop.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With