Scala构造函数中的变量参数

时间:2014-09-07 14:34:53

标签: scala

我想在Scala中编写一个Matrix类,我可以实例化这样的对象:

val m1 = new Matrix( (1.,2.,3.),(4.,5.,6.),(7.,8.,9.) )

val m2 = new Matrix( (1.,2.,3.),(4.,5.,6.) )

val m3 = new Matrix( (1.,2.),(3.,4.) )

val m4 = new Matrix( (1.,2.),(3.,4.),(5.,6.) )

我试过这个:

class Matrix(a: (List[Double])* ) { }

然后我得到一个类型不匹配,因为矩阵行不是List [Double]类型。

此外,只需输入整数(1,2,3)而不是(1.,2.,3。),但仍然可以得到双矩阵。

如何解决这个问题?

谢谢! 马尔特

3 个答案:

答案 0 :(得分:1)

(1.0, 2.0)Tuple2[Double, Double]而不是List[Double]。同样,(1.0, 2.0, 3.0)Tuple3[Double, Double, Double]

如果你需要处理固定数量的基数,普通香草scala中最简单的解决方案就是

class Matrix2(rows: Tuple2[Double, Double]*)
class Matrix3(rows: Tuple3[Double, Double, Double]*)

等等。

由于存在从IntDouble的隐式转换,您可以传递一个int元组,它会自动转换。

new Matrix2((1, 2), (3, 4))

如果您需要对行基数进行抽象,使用类型强制执行NxM,则必须使用一些更复杂的解决方案,可能使用无形库。

或者您可以使用实际列表,但是您不能限制基数,即您不能确保所有行具有相同的长度(再次,在vanilla scala中,无形可以帮助)

class Matrix(rows: List[Double]*)
new Matrix(List(1, 2), List(3, 4))

最后,自scala 2.10起,1.文字语法已被弃用,并在scala 2.11中删除。请改用1.0

答案 1 :(得分:1)

如果您需要支持非常大的矩阵,请考虑使用现有的实现,如Breeze。 Breeze有DenseMatrix,可能符合您的要求。出于性能原因,Breeze将更复杂的操作卸载到本机代码中。

使矩阵代数正确是一项艰难的练习,除非您专门实施矩阵学习/分配,否则最好使用经过验证的库。

根据以下评论进行编辑:

您可以考虑以下设计。

class Row(n : Int*)
class Matrix(rows: Row*) {...}

用法:

val m = new Matrix(Row(1, 2, 3), Row(2,3,4))

您需要验证所有行的长度并拒绝输入(如果不是。

答案 2 :(得分:0)

我已经破解了一个解决方案 - 我认为 - 有点不可思议的方式

class Matrix(values: Object*) { // values is of type WrappedArray[Object]
  var arr : Array[Double] = null
  val rows : Integer = values.size
  var cols : Integer = 0

  var _arrIndex = 0
  for(row <- values) {
    // if Tuple (Tuple extends Product)
    if(row.isInstanceOf[Product]) {
      var colcount = row.asInstanceOf[Product].productIterator.length
      assert(colcount > 0, "empty row")
      assert(cols == 0 || colcount == cols, "varying number of columns")
      cols = colcount

      if(arr == null) {
        arr = new Array[Double](rows*cols)
      }

      for(el <- row.asInstanceOf[Product].productIterator) {
        var x : Double = 0.0
        if(el.isInstanceOf[Integer]) {
          x = el.asInstanceOf[Integer].toDouble
        }
        else {
          assert(el.isInstanceOf[Double], "unknown element type")
          x = el.asInstanceOf[Double]
        }

        arr(_arrIndex) = x
        _arrIndex = _arrIndex + 1
      }
    }
  }
}

就像

一样
object ScalaMatrix extends App {
  val m1 = new Matrix((1.0,2.0,3.0),(5,4,5))
  val m2 = new Matrix((9,8),(7,6))
  println(m1.toString())
  println(m2.toString())
}

我真的不喜欢它。你觉得怎么样?