class 扩展特征 Iterator 中的覆盖方法 map 和 flatMap
Overriding methods map and flatMap in class extending trait Iterator
作为 Scala 初学者,我正在尝试为在 for
表达式中检索和处理的 Iterator
的每个项目实现一个计数器,并在每次新迭代时增加一个计数器表达式的 "loops" 之一开始(外循环和嵌套循环)。要求是在不简单地在 for
表达式的多个位置放置像 counter = counter + 1
这样的语句的情况下完成此操作。
下面的清单显示了我针对这个问题提出的解决方案,我想知道,为什么方法 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
的 map
和 flatMap
并没有像我有限的大脑所期望的那样工作 ;-)
此致
马丁
你的台词
List(...) <- Iterator
不要调用地图和平面图。他们在 List 伴随对象中调用 unapply,该对象将 Iterators 解包为元组。
要调用 map 或 flatMap 你需要类似的东西
item <- Iterator
您需要使用 unapply 方法为 InstrumentedIter 定义伴随对象,或者在您的理解中使用 map/flatMap 语法。
与此同时,我自己也找到了答案。我的解决方案的问题是 withFilter returns 是对新创建的 AbstractIterator 的引用,而不是 InstrumentedIterator。作为一种可能的解决方案,可以将此引用传递给包装器 class 的构造函数,例如 InstrumentedIterator,它混合了 trait Iterator 并覆盖了 map 和 flatMap 方法。然后这些方法可以进行计数...
问候
马丁
作为 Scala 初学者,我正在尝试为在 for
表达式中检索和处理的 Iterator
的每个项目实现一个计数器,并在每次新迭代时增加一个计数器表达式的 "loops" 之一开始(外循环和嵌套循环)。要求是在不简单地在 for
表达式的多个位置放置像 counter = counter + 1
这样的语句的情况下完成此操作。
下面的清单显示了我针对这个问题提出的解决方案,我想知道,为什么方法 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
的 map
和 flatMap
并没有像我有限的大脑所期望的那样工作 ;-)
此致
马丁
你的台词
List(...) <- Iterator
不要调用地图和平面图。他们在 List 伴随对象中调用 unapply,该对象将 Iterators 解包为元组。
要调用 map 或 flatMap 你需要类似的东西
item <- Iterator
您需要使用 unapply 方法为 InstrumentedIter 定义伴随对象,或者在您的理解中使用 map/flatMap 语法。
与此同时,我自己也找到了答案。我的解决方案的问题是 withFilter returns 是对新创建的 AbstractIterator 的引用,而不是 InstrumentedIterator。作为一种可能的解决方案,可以将此引用传递给包装器 class 的构造函数,例如 InstrumentedIterator,它混合了 trait Iterator 并覆盖了 map 和 flatMap 方法。然后这些方法可以进行计数...
问候 马丁