在评估最后一个表达式时,有没有人知道/解释为什么REPL会被卡住?奇怪的是,它不会抛出任何异常或任何东西,只是没有任何反应。
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
提前感谢您的任何解释。
答案 0 :(得分:6)
以下是发生的事情。在Scala REPL中定义迭代器时,会打印有关该迭代器的一些信息,无论它是否为空:
scala> Iterator.continually(List(1)).flatten
res1: Iterator[Int] = non-empty iterator
此信息由toString
Iterator
方法返回,其定义如下:
override def toString = (if (hasNext) "non-empty" else "empty")+" iterator"
基本上,在新创建的迭代器上调用hasNext
。现在让我们看看hasNext
在你的案例中做了什么(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()
}
}
啊哈! hasNext
以递归方式遍历迭代器,试图找到一个结尾或一个非空元素。在你的情况下,永远不会发生,因为你有无限的空元素迭代器。所以,你有一个由REPL触发的无限循环。你没有得到StackOverflow
,因为使用了尾递归,而在scala中它被转换为while循环。