scalainheritancecollectionsiterator-traits

Overriding methods map and flatMap in class extending trait Iterator


As a Scala beginner I'm trying to implement a counter for every item of an Iterator being retrieved and processed in a for expression as well as a counter incremented every time a new iteration over one of the "loops" of the expression (outer loop and nested loops) is started. The requirement is to accomplish this without simply placing a statement like counter = counter + 1 at numerous locations in the for expression. The following listing shows my proposed solution to this problem and I would like to know, why method next implementing Iterator's abstract member gets called (and the corresponding counter is incremented) whereas flatMap and map overriding their pendants defined in trait Iterator (and calling them via super) are not called at all.

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 

The corresponding for expression looks like this:

  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

I would be grateful if someone could give me a hint how to solve the given problem in a better way. But most of all I am interested to know why my solution overriding Iterator's map and flatMap doesn't work like expected by my somewhat limited brain ;-)

Regards

Martin


Solution

  • In the meanwhile I managed to find the answer myself. The problem with my solution is that withFilter returns a reference to a newly created AbstractIterator, not an InstrumentedIterator. As a possible solution this reference can be passed to the constructor of a wrapper class like InstrumentedIterator that mixes in trait Iterator and overrides methods map and flatMap. These methods can then do the counting ...

    Regards Martin