下面第一段代码背后的意图是为iterables定义一个新特征,它提供了一个额外的方法,用于在迭代前面添加一个新元素。
但是,在第二个代码段中运行代码时,我们发现+:
方法会返回一个迭代,产生无穷大的0
s。
我做错了什么,我怎样才能达到预期的行为?
注意:我添加了outer
val以确保在定义+:
返回的对象的方法时获得正确的迭代器;我不知道如何访问该迭代器(Iterable2.this.iterator
没有编译)。
trait Iterable2[A] extends Iterable[A] {
val outer :Iterable[A] = this
def +:(elem :A) = new Iterable2[A] {
override def iterator: Iterator[A] = new Iterator[A] {
private[this] var virgin = true
override def hasNext: Boolean = virgin || outer.iterator.hasNext
override def next(): A = {
if (virgin) {virgin = false; elem}
else outer.iterator.next()
}
}
}
}
val i = new Iterable2[Int] {
override def iterator: Iterator[Int] = Iterator(1,2,3)
}
for (j <- 0 +: i) {
println(j)
}
答案 0 :(得分:1)
outer.iterator
将始终为您提供一个新的迭代器。你需要创建一个并将其藏匿在某处,然后使用那个单独存储的而不是每次都创建一个新的:
new Iterator[A] {
val outerIterator = outer.iterator
override def hasNext = ...
}
答案 1 :(得分:0)
我的原始代码中的第一个错误是outer.iterator
每次评估时都会返回一个新的迭代器,正如@DiegoMartinoia和@Imm所指出的那样。
但是,正如@misberner所建议的那样,还需要将val outer = this
替换为outer =>
。
目前,这只是我问题的部分答案,因为它无法解释为什么第二次更改是必要的。
因此修正后的特质代码为:
trait Iterable2[A] extends Iterable[A] {
outer :Iterable[A] =>
def +:(elem :A) = new Iterable2[A] {
override def iterator: Iterator[A] = new Iterator[A] {
private[this] var virgin = true
private[this] val underlyingIterator = outer.iterator
override def hasNext: Boolean = virgin || underlyingIterator.hasNext
override def next(): A = {
if (virgin) {virgin = false; elem}
else underlyingIterator.next()
}
}
}
}