我的数组的Scala参数化假定为String?

时间:2012-06-20 22:07:51

标签: scala parameterization

我已经阅读了一些关于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“必需”?

2 个答案:

答案 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
}