Scala自定义集合未能在中选择正确的映射函数进行理解



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

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

现在我想添加所需的理解方法。我定义了两个不同的映射函数。一个返回List,另一个返回相同的数据类型(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循环要么选择返回List的第一个map,要么抛出一个神秘错误。以下示例产生错误:

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

我错过了什么?

[更新]

这里提供了完整的实现要点。

问题与类型不匹配有关,您将传递给map的函数定义为两个参数的函数(Int&T(X。而在你的理解中,你将其视为一个参数(元组(Int, T)(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

请参阅ScalaMapmap的完整签名作为参考。