获得正确的迭代器

时间:2014-11-23 18:08:15

标签: scala anonymous

下面第一段代码背后的意图是为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)
}

2 个答案:

答案 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()
      }
    }
  }
}