我已经阅读了一些关于Manifest和擦除避免技术的内容,这些技术允许Scala执行“new Array [Array [T]]”之类的操作,但我对这个有点难过......
我有一种方法可以将数组中的一堆行列表为电子表格。例如,想象一下像这样的2D数组:
11, 5, 4
8, 3, 7
2, 1, 4
我编写了一个方法,总结了该数组的列并吐出了像[21,9,15]这样的一维数组
我想将其泛化为Ints(可能是Doubles或Floats),当我添加参数和清单时,我会收到编译错误。
这是代码
def sumGrid[T](grid: Array[Array[T]])(implicit m: ClassManifest[T]): Array[T] = {
val sum = new Array[T](grid(0).size)
for(i <- 0 until grid.size) {
for(j <- 0 until grid(0).size) {
sum(j) = sum(j) + grid(i)(j)
}
}
sum
}
这是编译错误:
[ERROR] ...scala/euler/GridOperations.scala:126: error: type mismatch;
[INFO] found : T
[INFO] required: String
[INFO] sum(j) = sum(j) + grid(i)(j)
[INFO] ^
[ERROR] one error found
这里发生了什么?为什么String“必需”?
答案 0 :(得分:6)
因为您使用始终为字符串定义的+
运算符。任何类型都可以转换为String(始终定义toString
),因此它适用于任何类型T
。
但是你可以在T
上添加一些约束以确保它对应于算术运算。例如,您可以使用implicits获取Numeric
个对象来定义类型T
的添加:
def sumGrid[T](grid: Array[Array[T]])
(implicit m: ClassManifest[T], num: Numeric[T]): Array[T] = {
val sum = new Array[T](grid(0).size)
for(i <- 0 until grid.size) {
for(j <- 0 until grid(0).size) {
sum(j) = num.plus( sum(j), grid(i)(j) )
}
}
sum
}
答案 1 :(得分:0)
您处理了Array
部分,但T
没有任何约束表明它有+
方法。因此,Scala认为您正在添加字符串 - 当您将其添加到另一个String
时,它会自动将任何类型转换为String
。因此,它会自动将sum(j)
转换为String
,现在希望grid(i)(j)
成为另一个String
,此时它会放弃并失败。
您可以通过与T
内容类似的方式处理有关ClassManifest
数字的事情。这里:
// I'm using the "context bound" notation, to make the declaration shorter and
// more obvious on what I'm saying about T
def sumGrid[T : ClassManifest : Numeric](grid: Array[Array[T]]): Array[T] = {
// the following line, plus the Numeric bound, makes T usable as a number
import scala.math.Numeric.Implicits._
val sum = new Array[T](grid(0).size)
for(i <- 0 until grid.size) {
for(j <- 0 until grid(0).size) {
sum(j) = sum(j) + grid(i)(j)
}
}
sum
}