1

我已经阅读了一些关于 Manifests 和允许 Scala 执行诸如“new Array[Array[T]]”之类的操作所需的避免擦除技术,但我对这个有点难过......

我有一种方法可以将数组中的一堆行列成表格,就像电子表格一样。例如想象一个像这样的二维数组:

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

这里发生了什么?为什么字符串是“必需的”?

4

2 回答 2

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
}
于 2012-06-20T22:18:22.070 回答
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
}
于 2012-06-20T23:09:00.277 回答