在类扩展trait Iterator中覆盖方法map和flatMap

时间:2015-04-18 12:35:55

标签: scala inheritance collections iterator-traits

作为一名Scala初学者,我正在尝试为Iterator表达式中for的每个项目实现一个计数器,并且每次在一个新迭代时都会增加一个计数器启动表达式(外循环和嵌套循环)的“循环”。要求是完成此操作而不是简单地在counter = counter + 1表达式中的多个位置放置for之类的语句。 下面的清单显示了我对这个问题的建议解决方案,我想知道为什么实现next的抽象成员的方法Iterator被调用(并且相应的计数器递增),而flatMap并且map覆盖特征Iterator中定义的垂饰(并通过super调用它们)根本不会被调用。

object ZebraPuzzle {
  var starts = 0
  var items = 0

  class InstrumentedIter[A](it: Iterator[A]) extends Iterator[A] {
    private val iterator = it

    def hasNext = it.hasNext

    def next() = {
      items = items + 1
      it.next()
    }

    override def flatMap[B](f: (A) ⇒ GenTraversableOnce[B]): Iterator[B] = {
      starts = starts + 1
      super.flatMap(f)
    }

    override def map[B](f: (A) ⇒ B): Iterator[B] = {
      starts = starts + 1
      super.map(f)
    }
  } // inner class InstrumentedIter 

相应的for表达式如下所示:

  def solve = {
    val first = 1
    val middle = 3
    val houses = List(first, 2, middle, 4, 5)
    for {
      List(r, g, i, y, b) <-  new InstrumentedIter(houses.permutations)
      if ...
      List(eng, span, ukr, jap, nor) <- new InstrumentedIter(houses.permutations)
      if ...
      if ...
      if ...
      List(of, tea, milk, oj, wat) <- new InstrumentedIter(houses.permutations)
      if ...
      ...
    } yield ...
  ...
  }
...
} // standalone singleton object ZebraPuzzle

如果有人能给我一个如何以更好的方式解决问题的提示,我将不胜感激。但最重要的是我很有兴趣知道为什么我的解决方案覆盖Iterator的{​​{1}}和map不能像我有限的大脑预期的那样工作; - )

此致

马丁

2 个答案:

答案 0 :(得分:0)

与此同时,我设法找到答案。我的解决方案的问题是withFilter返回对新创建的AbstractIterator的引用,而不是InstrumentedIterator。作为一种可能的解决方案,这个引用可以传递给一个包装类的构造函数,比如InstrumentedIterator,它混合在trait Iterator中并覆盖方法map和flatMap。然后这些方法可以进行计数......

此致 马丁

答案 1 :(得分:-1)

你的行

List(...) <- Iterator

不要调用map和flatmap。它们在List伴侣对象中调用unapply,它将迭代器解包为元组。

要调用map或flatMap,您需要类似

的内容
item <- Iterator

您需要使用unapply方法为InstrumentedIter定义一个伴随对象,或者在for comprehension中使用map / flatMap语法。