为什么这个迭代器无限循环?

问题描述 投票:2回答:1

我正在尝试链接Iterators

var it = Iterator(1)
it.next
it = Iterator(2) ++ it
it.next
it.hasNext

这在hasNext上无限循环,如您在此处看到的:https://scastie.scala-lang.org/qbHIVfsFSNO5OYmT4pkutA

如果运行此程序并在堆栈无限循环时对其进行检查,则堆栈中的内容将循环播放:

        at scala.collection.Iterator$ConcatIterator.merge(Iterator.scala:213)
        at scala.collection.Iterator$ConcatIterator.advance(Iterator.scala:197)
        at scala.collection.Iterator$ConcatIterator.hasNext(Iterator.scala:227)

(此堆栈来自Scala 2.12.11,但Scastie链接在2.13.2中显示相同的行为。

我知道[在调用它的方法后,永远不要使用迭代器,但这似乎对我有用。使用var指向“当前”迭代器,然后将其更改为指向一个新的迭代器,该迭代器将附加上一个迭代器的其余部分。

下面的一些修改确实有效:

var it = Iterator(1)
it.next
val x = it
it = Iterator(2) ++ x
it.next
it.hasNext

Scastie链接:https://scastie.scala-lang.org/1X0jslb8T3WIFLHamspYAg

这向我暗示,坏版本以某种方式创建了一个追加自身的Iterator。关于这里发生的事情有什么提示吗?

scala
1个回答
0
投票

++Iterator方法的参数按名称传递。 ++返回一个新的Iterator,它仅存储一个返回it的函数,但是直到您尝试使用附加的元素时才调用它。

因此++仅在调用it.hasNext时尝试评估该参数,但是到那时it已经作为++的结果重新定义,因此最终尝试将it附加到其自身上。

换句话说,var和同名参数不能一起使用。

因此,请勿将Iterator方法的结果重新分配给相同的变量,而应给它们重新命名:

val it = Iterator(1)
it.next
val it2 = Iterator(2) ++ it
it2.next
it2.hasNext
© www.soinside.com 2019 - 2024. All rights reserved.