2011-08-10 109 views
0

給出一個簡單的矩陣實現斯卡拉混淆的可變性和陣列/列表

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 } 
... 
} 

我的理解可變性意味着我不能重新分配矩陣,但在它我可以設置新值。如set()所示。

現在添加的實施已被打破,但我堅持如何最好地實施它。我希望使用變換

def add(scalar:Double) { matrix.transform(_.transform(_ + scalar)) } 
// type mismatch; found : ...WrappedArray[Double] required: Array[Double] 

但我不能讓它編譯。那麼有沒有辦法讓上面的例子工作?

並請隨時敲定任何瑕疵,我約列表/陣列的可變性邏輯:P

+0

另外,問題是,你想達到什麼目的?不可變的代碼或可變的代碼,或者只是某種程度上正常的代碼? – coubeatczech

+0

矩陣應該保持不變 – npiv

回答

4

事實上,你不能重新分配到matrix,因爲它是一個val(參考是不可變的)。 Array的實例可以改變,因爲Array的接口允許,這使得它成爲一個可變類。

所以matrix =是不允許的。與matrix.map的通話是有效的,它會創建一個新的陣列,保持matrix不變。由於第二個map,它也會更改matrix中的子陣列。不是你想要的。最後,結果不可分配給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中的細節,最後)。方法transformWrappedArray。它的返回類型必須是WrappedArray,因爲變換在類型層次結構中定義得非常好,並且強制結果爲this。這意味着transform不應該被用於數組。所以你必須去foreach

1

你需要做一些與matrix.map(_.map(_ + scalar))的返回值。創建基於該值的新矩陣並返回它:

def add(scalar:Double) = { new Matrix(matrix.map(_.map(_ + scalar))) } 

您不能分配到matrix再次,因爲這是(指定一個新值unability)的val屬性。
的使用則是:

val matrix = new Matrix(Array(Array(1,2))) 
val newMatrix = matrix.add(5)