【发布时间】:2014-11-23 18:08:14
【问题描述】:
下面第一个 sn-p 代码的目的是为可迭代对象定义一个新特征,它提供了一种在可迭代对象前面添加新元素的附加方法。
但是,当在第二个 sn-p 中运行代码时,我们看到 +: 方法返回一个迭代器,产生无穷大 0s。
我做错了什么以及如何获得预期的行为?
注意:我添加了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)
}
【问题讨论】:
-
抛出一个猜测:是否将迭代器重写为 def 意味着它每次都重新计算新的迭代器,因此总是添加形式为 0,1,2,3 的新迭代器,但总是从0?
-
在风格上:你不需要为
outer引入val,对外部对象的显式引用也可以(并且可以说更优雅)通过替换@来实现987654331@ 与outer =>一致。 -
谢谢你,@misberner!我希望有人能评论如何正确地做到这一点。我发现 this Scala 文档文章介绍了
outer =>语法结构,尽管目的不同。也许有更好的参考? -
事实上,@misberner,将
val outer :Iterable[A] = this更改为outer =>不仅仅是风格。我发现这是必要的,并且与@Imm 的修复相结合,足以产生所需的行为。我想知道为什么。