2014-11-23 81 views
0

下面第一段代码的目的是为迭代器定义一个新的特征,它提供了一个额外的方法,用于在迭代器前面添加一个新的元素。获得正确的迭代器

但是,在第二个代码段中运行代码时,我们看到+:方法返回一个可迭代的结果,产生0的无穷大。

我在做什么错,我如何得到预期的行为?

注:我添加了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) 
} 
+1

投掷猜测在那里:会不会是重写迭代作为DEF意味着它重新计算新的迭代,每次,从而总是加上形式0的新的迭代,1,2,3但总是从0开始? – 2014-11-24 10:53:37

+1

在文体上说明:不需要为'outer'引入'val',通过将'val outer'行替换为'outer',也可以(并且可以更优雅地)显式引用外部对象=>'。 – misberner 2014-11-24 11:18:23

+0

谢谢@misberner!我希望有人会评论如何做到这一点。我发现[this](http://docs.scala-lang.org/tutorials/tour/explicitly-typed-self-references.html)Scala文档介绍了'outer =>'语法结构,尽管出于不同的目的。也许有更好的参考? – 2014-11-26 09:29:18

回答

0

在我的原代码中的第一个错误是,outer.iterator每它的评估时间返回一个新的迭代器正如@DiegoMartinoia和@Imm所指出的那样。

但是,如@misberner所建议的,还需要用outer =>替代val outer = this

现在,这只是我的问题的部分答案,因为它不能解释为什么第二次更改是必要的。

校正性状码是这样的:

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() 
     } 
    } 
    } 
} 
1

outer.iterator总会给你一个新的迭代。您需要创建一个某处藏匿,然后使用单藏匿一个,而不是创建一个新的每次:

new Iterator[A] { 
    val outerIterator = outer.iterator 
    override def hasNext = ... 
} 
+0

的确,我没有想到这一点。但是,这不足以产生所需的行为。它需要与@ misberner的建议相结合。 – 2014-11-26 09:48:49