Scala 自定义集合无法在理解中选择正确的映射函数

Scala custom collection fails to pick correct map function in for-comprehension

我实现了一个自定义集合 class,它基本上是一个 Map,带有隐式整数键和值,是 AnyRef 的子class。它使用 Int 键作为底层数组结构的索引。这是 class 声明签名(class 实例化是在伴随对象中完成的,因此是私有构造函数):

class ArrayMap[T >: Null <: AnyRef: ClassTag] private (private var data: Array[T]) { self =>
   ...
}

现在我想添加理解所需的方法。我定义了两个不同的地图函数。一个 returns 一个 List 和另一个 returns 相同的数据类型 (ArrayMap).

def map[X](f: (Int, T) => X): List[X] = { ... }
def map[X >: Null <: AnyRef: ClassTag](f: (Int, T) => X): ArrayMap[X] = { ... }
def foreach(f: (Int, T) => Unit): Unit = { ... }
def flatMap[X >: Null <: AnyRef: ClassTag](f: (Int, T) => Iterable[(Int, X)]): ArrayMap[X] = { ... }
def filter(p: (Int, T) => Boolean): ArrayMap[T] = { ... }

没有定义隐式。单独使用时,上述功能按预期工作。问题在于理解。 For 循环要么选择第一个 map 哪个 returns List 要么抛出一个神秘的错误。以下示例产生错误:

val map = ArrayMap.empty[Integer]
map(0) = 0
map(1) = 1
map(5) = 2
map(6) = 3
map(10) = 4

val rs: ArrayMap[String] = for (e <- map) yield e._2.toString

以上代码抛出:

Error:(293, 41) missing parameter type
        val rs: ArrayMap[String] = for (e <- map) yield e._2.toString

我错过了什么?

[更新]

完整的实现可作为要点 here

问题与类型不匹配有关,您将要传递给 map 的函数定义为两个参数 (Int & T) 的函数X。而在您的理解中,您将其视为一个参数的函数 (a tuple (Int, T)) to X.

最简单的解决方案是重新定义您的 map 函数签名。 例如

import scala.reflect.ClassTag

class ArrayMap[T >: Null <: AnyRef: ClassTag] (val data: Array[T]) {
  // Note the double parenthesis (()).
  def map[X >: Null <: AnyRef: ClassTag](f: ((Int, T)) => X): ArrayMap[X] = ???
  def withFilter(p: ((Int, T)) => Boolean): ArrayMap[T] = ???
}

有了这个定义,你可以做出类似

的东西
val map: ArrayMap[java.lang.Integer] = new ArrayMap(Array(1, 2, 3))

// Note I use lazy val to avoid the NotImplementedException.
lazy val rs1: ArrayMap[String] = map.map(tuple => tuple._2.toString)

lazy val rs2: ArrayMap[String] = map.map { case (_, v) => v.toString }

lazy val rs3: ArrayMap[String] = for {
  tuple <- map
} yield tuple._2.toString

lazy val rs4: ArrayMap[String] = for {
  (_, v) <- map
} yield v.toString

参见 Scala Mapmapfull signature 作为参考。