给出一个简单的Matrix实现
class Matrix(val matrix: Array[Array[Double]]) {
...
def add(scalar:Double) { matrix.map(_.map( _ + scalar )) }
def set(row:Int,col:Int,value:Double) { matrix(row)(col) = value }
...
}
据我所知,Mutability意味着我无法重新分配矩阵,但我可以在其中设置新值。正如set()工作所证明的那样。
现在添加的实现已被打破,但我仍然坚持如何最好地实现它。我对使用transform
充满希望def add(scalar:Double) { matrix.transform(_.transform( _ + scalar )) }
// type mismatch; found : ...WrappedArray[Double] required: Array[Double]
但是我无法编译它。那么有一种方法可以让上面的例子起作用吗?
请随意解决我的逻辑中有关列表/数组可变性的任何缺陷:P
答案 0 :(得分:4)
实际上,您无法重新分配给matrix
,因为它是val
(引用是不可变的)。可以更改Array
的实例,因为Array
的接口允许,这使得它成为可变类。
因此不允许matrix =
。 matrix.map
的调用有效,它会创建一个新数组,保持matrix
不变。由于第二个matrix
,它还会更改map
内的子数组。不是你想要的。最后,结果无法分配给matrix
,因为不允许分配给matrix
transform
确实是要走的路。但是您想要更改的数组是matrix
(行)中的数组,而不是matrix
本身,它们仍应包含相同(但已更改)的行。正确的电话是
matrix.foreach(_.transform(_ + scalar)
然而,你的版本应该有效。 transform
返回呼叫的目标。关键是你可以链接来电,a.transform(...).doSomethingElse().andAgain()
(这里你不需要)。所以你的matrix.transform应该是一个变换(身份) - 副作用是这个特定的身份会改变行的内容,这本来就没问题。
问题是转换实际上不是Array的方法(数组在JVM中并且没有这样的方法)。它来自隐式转换。从Array有两个值得注意的隐式转换,一个到ArrayOps
,另一个到WrappedArray
(文章Fighting Bit Rot with Types中的详细信息,到最后)。方法transform
位于WrappedArray
。它的返回类型必须是WrappedArray
,因为变换在类型层次结构中定义得很好,并强制结果为this
。这意味着transform
不太有趣的结果不应该用于数组。所以你必须选择foreach
。
答案 1 :(得分:1)
您需要使用matrix.map(_.map( _ + scalar ))
的返回值执行某些操作。根据此值创建一个新矩阵并将其返回:
def add(scalar:Double) = { new Matrix(matrix.map(_.map( _ + scalar ))) }
您无法再次分配给matrix
,因为这是val
的属性(无法分配新值)。
用法是:
val matrix = new Matrix(Array(Array(1,2)))
val newMatrix = matrix.add(5)