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
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