说我有一个例如二维数组,我在元组中存储一些索引:
val testArray = Array.ofDim[Double](3, 4)
val ixs = (1,2)
我想直接使用这些元组,例如testArray(ixs)
。但是,Function.tupled(testedArray _)
返回“_必须遵循方法;不能跟随数组[数组[双]]”。
这是因为Array
实际上不是Function3
的子类型吗? 如果是这样,如何解决这个限制?我应该使用implicits来扩展ArrayOps
或类似内容吗?目前,我将数据存储在Map
中作为解决方法。
答案 0 :(得分:2)
阵列阵列没有得到特殊处理;他们只是(某事)的数组。因此,没有通过元组访问它们的特殊方法。但正如你所建议的,你可以创造这样一种方式。
你可以
implicit class ArrayOps2D[@specialized T](xss: Array[Array[T]]) {
def apply(ij: (Int, Int)) = xss(ij._1)(ij._2)
def apply(i: Int, j: Int) = xss(i)(j)
def update(ij: (Int, Int), t: T) { xss(ij._1)(ij._2) = t }
def update(i: Int, j: Int, t: T) { xss(i)(j) = t }
}
您可能会想到
implicit class ArrayOps2D[T](val xss: Array[Array[T]]) extends AnyVal {
def apply(ij: (Int, Int)) = xss(ij._1)(ij._2)
def apply(i: Int, j: Int) = xss(i)(j)
def update(ij: (Int, Int), t: T) { xss(ij._1)(ij._2) = t }
def update(i: Int, j: Int, t: T) { xss(i)(j) = t }
}
但在我看来,这并不奏效。由于实施限制,您无法专门化AnyVal。此外,前者可能更好,如果你使用原语很多,因为它避免装箱原语(并且JVM可以处理避免对象创建,希望如此),而后者在大多数时候有非原语时效率更高(因为你没有(正式)创建一个对象。但是你的例子使用了原语。
在任何情况下,如果你这样做,你将使用元组和参数对进行无缝的双索引寻址(就像我写的那样)。但无法完全无缝地使用更新方法!它们大部分都可以使用,但是不会自动提升数字类型。因此,如果你有双打并且你写a(1,2) = 3
它会失败,因为它找不到update(Int, Int, Int)
方法,并且不认为使用update(Int, Int, Double)
。但是你可以通过转换来解决这个问题(或者在这种情况下写3d
)。