【问题标题】:Scala implicit ClassManifest[T] is null in Array.fill(..)Scala 隐式 ClassManifest[T] 在 Array.fill(..) 中为空
【发布时间】:2011-07-09 00:36:30
【问题描述】:

我开始在 Scala 中使用泛型,这是一个很难破解的 cookie。我的想法是通过编写一个用于我的并行计算项目的通用矩阵类来学习它。

但是,在实例化新矩阵时,我无法使用 Array.fill()。这是我的矩阵代码:

(小心砖墙)


package dm8xx.matrix.immutable
import scala.util.Random

/*
 * Bring your sunglasses...
 */

object Matrix {
  def apply[T](m: Int, n: Int, v: T )(implicit nn:Numeric[T],mm:ClassManifest[T]): Matrix[T] = {
    println("making new mat")
    println(mm)
      new Matrix[T](Array.fill(m,n)(v))
  }
  def apply[T: Numeric](m: Int, n: Int): Matrix[T] = Matrix(m, n)
  def apply(m: Int, n: Int, r: Random): Matrix[Double] =
    new Matrix(Array.fill[Double](m, n) { Math.floor(r.nextDouble() * 100) })

}

class Matrix[T: Numeric](val data: Array[Array[T]]) {
  val num = implicitly[Numeric[T]]
  implicit val cm: ClassManifest[T] = implicitly
  val m = data.size
  val n = data(0).size
  def apply(i: Int, j: Int) = data(i)(j)

  def map(f:T=>T)= new Matrix(data.map(_.map(f)))

  def pieceWise(f: (T, T) => T, that: Matrix[T]): Matrix[T] = {
    val temp: Array[Array[T]] = Array.ofDim[T](m, n)
    for (i <- 0 until m; j <- 0 until n) temp(i)(j) = f(data(i)(j), that.data(i)(j))
    return new Matrix(temp)
  }
  def +(that: Matrix[T]) = pieceWise(num.plus(_, _), that)
  def -(that: Matrix[T]) = pieceWise(num.minus(_, _), that)
  def *(that: Matrix[T]) = {
    val temp = Matrix[T](m,that.n,num.one)
    for (i <- 0 until m; j <- 0 until n; k <- 0 until that.n)
      temp.data(i)(k) = num.plus(temp.data(i)(k) , num.times( data(i)(j) , that.data(j)(k)))
    temp
  }

  override def toString() = (for (i <- 0 until m) yield "\n" + (for (j <- 0 until n) yield data(i)(j))).toString

}

一切都可以编译,我什至可以运行我的测试,但它在某个时候失败了。我正在运行的测试如下:

  val M = 100
  val N = 100
  val threads = false
  def main(args: Array[String]) {
    val r = new Random(2)
    val a: Matrix[Double] = Matrix(M, N, r)
    val b: Matrix[Double] = Matrix(N, M, r)
    println(a)
    println(b)
    var m12 = a * b
  }

这会失败,但有以下异常:

Exception in thread "main" scala.MatchError: null
    at scala.reflect.ClassManifest$.arrayType(ClassManifest.scala:206)
    at scala.Array$.fill(Array.scala:254)
    at dm8xx.matrix.immutable.Matrix$.apply(Matrix.scala:12)
    at dm8xx.matrix.immutable.Matrix.$times(Matrix.scala:37)
    at dm8xx.matrix.MatrixTest$.main(MatrixTest.scala:19)
    at dm8xx.matrix.MatrixTest.main(MatrixTest.scala)

有人能告诉我为什么此时类清单为空吗?很抱歉放了这么多代码,但我不知道我的错误在哪一点,所以我必须报告所有内容。 (也许当我得到一个好的答案时,我可以删除不相关的部分)。



好的,现在代码可以工作了,但当然它至少比使用 Double 的直接实现慢 10 倍……这就是最终矩阵的样子(如果有人感兴趣的话):

package dm8xx.matrix.immutable
import scala.util.Random

/*
 * Bring your sunglasses...
 */

object Matrix {
  def apply[T](m: Int, n: Int, v: T)(implicit nn: Numeric[T], mm: ClassManifest[T]): Matrix[T] = {
    new Matrix[T](Array.fill(m, n)(v))
  }
  def apply[T](m: Int, n: Int)(implicit num: Numeric[T], cm: ClassManifest[T]): Matrix[T] = Matrix[T](m, n, num.zero)
  def apply(m: Int, n: Int, r: Random): Matrix[Double] =
    new Matrix(Array.fill[Double](m, n) { Math.floor(r.nextDouble() * 100) })
}

class Matrix[T: Numeric: ClassManifest](val data: Array[Array[T]]) {
  val num = implicitly[Numeric[T]]
  val cm: ClassManifest[T] = implicitly
  val m = data.size
  val n = data(0).size
  def apply(i: Int, j: Int) = data(i)(j)

  def map(f: T => T) = new Matrix(data.map(_.map(f)))

  def pieceWise(f: (T, T) => T, that: Matrix[T]): Matrix[T] = {
    val temp: Array[Array[T]] = Array.ofDim[T](m, n)
    for (i <- 0 until m; j <- 0 until n) temp(i)(j) = f(data(i)(j), that.data(i)(j))
    return new Matrix(temp)
  }
  def +(that: Matrix[T]) = pieceWise(num.plus(_, _), that)
  def -(that: Matrix[T]) = pieceWise(num.minus(_, _), that)
  def *(that: Matrix[T]) = {
    val temp = Matrix[T](m, that.n, num.zero)
    for (i <- 0 until m; j <- 0 until n; k <- 0 until that.n)
      temp.data(i)(k) = num.plus(temp.data(i)(k), num.times(data(i)(j), that.data(j)(k)))
    temp
  }

  override def toString() = (for (i <- 0 until m) yield "\n" + (for (j <- 0 until n) yield data(i)(j))).toString

}

【问题讨论】:

  • 有人可以推荐一个关于使用隐式值进行类型推断的很好解释,或者可以通过示例给出一个很好的简短解释吗?

标签: generics scala null matrix scala-2.8


【解决方案1】:

这似乎有效:

class Matrix[T: Numeric: ClassManifest](val data: Array[Array[T]]) {
  val num = implicitly[Numeric[T]]
  val cm: ClassManifest[T] = implicitly
...

【讨论】:

  • 是的。这是为什么?此外,如果有人感兴趣,在 * 函数中它应该是 num.zero 而不是 num.one。
  • @Felix 因为,否则,通过 data 创建新数组的方法将没有可用的 ClassManifest
【解决方案2】:

尝试使用Manifest 而不是ClassManifest

数组在包含原语时需要额外处理,因为它们已被具体化,但 ClassManifest 旨在与类一起使用(这个名字是一个赠品)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-08-08
    • 1970-01-01
    • 1970-01-01
    • 2018-10-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-03-16
    相关资源
    最近更新 更多