【问题标题】:Getting the Correct Iterator获取正确的迭代器
【发布时间】: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 =&gt; 一致。
  • 谢谢你,@misberner!我希望有人能评论如何正确地做到这一点。我发现 this Scala 文档文章介绍了 outer =&gt; 语法结构,尽管目的不同。也许有更好的参考?
  • 事实上,@misberner,将val outer :Iterable[A] = this 更改为outer =&gt; 不仅仅是风格。我发现这是必要的,并且与@Imm 的修复相结合,足以产生所需的行为。我想知道为什么。

标签: scala anonymous


【解决方案1】:

outer.iterator 总是会给你一个新的迭代器。您需要创建一个并将其存储在某处,然后使用该单个存储的而不是每次都创建一个新的:

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

【讨论】:

  • 没错,我没有想到这一点。但是,这不足以产生所需的行为。需要结合@misberner 的建议。
【解决方案2】:

正如@DiegoMartinoia 和@Imm 所指出的那样,我的原始代码中的第一个错误是outer.iterator 每次对其进行评估时都会返回一个新的迭代器。

但是,按照@misberner 的建议,还需要将val outer = this 替换为outer =&gt;

目前,这只是对我的问题的部分回答,因为它没有解释为什么需要进行第二次更改。

修正后的特征代码如下:

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-10-23
    • 2012-03-03
    • 2012-11-01
    • 2015-08-23
    • 2011-06-22
    • 1970-01-01
    • 1970-01-01
    • 2016-06-25
    相关资源
    最近更新 更多