Scala迭代器:“在调用方法后,永远不要使用迭代器”-为什么?

Ale*_*rov 4 iterator scala

关于Iterator [T]的Scala文档在此处表示以下内容:

特别重要的是要注意,除非另有说明,否则永远不要在调用迭代器后使用迭代器。两个最重要的例外也是唯一的抽象方法:nexthasNext

它们还给出了安全和不安全使用的特定示例:

def f[A](it: Iterator[A]) = {
  if (it.hasNext) {            // Safe to reuse "it" after "hasNext"
    it.next                    // Safe to reuse "it" after "next"
    val remainder = it.drop(2) // it is *not* safe to use "it" again after this line!
    remainder.take(2)          // it is *not* safe to use "remainder" after this line!
  } else it
}
Run Code Online (Sandbox Code Playgroud)

不幸的是,我在这里没有遵循不安全的想法。有人可以在这里给我一些启发吗?

Tra*_*own 5

这是一个具体的例子:

def eleventh[A](xs: Iterator[A]) = {
  xs.take(10).toList
  xs.next
}
Run Code Online (Sandbox Code Playgroud)

我们可以尝试一下:

scala> eleventh((1 to 100).toList.toIterator)
res0: Int = 11

scala> eleventh((1 to 100).toStream.toIterator)
res1: Int = 11

scala> eleventh(Stream.from(1).toIterator)
res2: Int = 11
Run Code Online (Sandbox Code Playgroud)

看起来不错 但是之后:

scala> eleventh((1 to 100).toIterator)
res3: Int = 1
Run Code Online (Sandbox Code Playgroud)

现在(1 to 100).toIterator的类型与相同(1 to 100).toList.toIterator,但两者在这里的行为有很大不同-我们看到实现细节从API中泄漏出来。这是一件非常糟糕的事情,并且是将纯功能组合器take与诸如迭代器之类的固有命令和可变概念混合在一起的直接结果。