2016-10-31 4 views
0

免責事項:私は本当にうまく私の質問を説明するか分からない。私は明確化のための提案に満足しています。これは、例えば問題ではありませんしながら、Scalaでは参照を変更してオリジナルを変更しないようにするにはどうすればいいですか?

val a = DenseVector.ones[Double](2) 
val b = a 
b(1 to 1) := 2.0 
a // return: breeze.linalg.DenseVector[Double] = DenseVector(1.0, 2.0) 

よう


物事は、私のような数学の男性のための問題の一種でありますin R

a = c(1,1) 
b = a 
b[1] = 2.0 
b // return: [1] 1 2 
a // return: [1] 1 1 

私は上記の現象がどのように呼び出されているのかわかりませんが、どうすれば避けられますか?私が正しく理解していれば、すべてのクラスでvalを使用することで回避されます不変のコレクションです。コレクションの不変なコレクションの並べ替えがあり、各エントリはvarの代わりにvalです。この非コピー・リファレンス・イシューは、オブジェクトに関数を与えるときにも起こります。何が起きるかははっきりしません(副作用ですが、新しく作成されたオブジェクトの代わりに返すとき)。 def myfct(val myparameter)でも、varのmyparameterが変更されないことを保証しないので、私はvalを排他的に与えるべきです。

これはすべてエラーが発生する可能性が高いです - 私はちょうど私が市長の間違いをするのを待っています。非常にまれにしか、深いコピーではなくオブジェクトへの参照を渡したいと思うだけです。ユニットテストは実際には唯一の方法ですか(また、発生する可能性のあるすべてのエラーを考えなくてはなりません)深いコピー(新しいオブジェクトを作成することによって明示的または暗黙的に)をすることを忘れないでテストできますか?

参照を変更してオリジナルを変更するのを間違えないようにするにはどうすればよいですか? valと不変なコレクションを使用する唯一の答えはありますか、別のデザインパターンがありますか?例えば。入力が変更可能なコレクションであっても、あるいは変更可能なメンバを持つオブジェクトであっても、関数への入力パラメータを不変にすることができるデザインパターンはありますか?

+1

Scalaは、あなたが望むように不変です:あなたが不変構造を使用する場合、それらは...まあ...不変です。変更可能なものを使用する場合、それらは変更できません。 私はあなたの問題が何であるかを理解していません。突然変異の可能性のあるものが好きでない場合は、使用しないでください。深いコピーをしないでください(非効率的で遅いです)。不変な構造体を使用してください。 – Dima

+0

'b [1] = 2.0'は、不変オブジェクトの操作のようには見えないので、おそらく不変性に関するものではありません。不変なオブジェクトを使用すると、参照問題は存在しません。そうでなければ最新のOOP言語はコピー参照のみを知っています。 –

+0

@Dima:私は私の質問を改善しようとしました。 – Make42

答えて

1

Scalaは可変オブジェクトを許可しています。breeze.linalg.DenseVectorは可変オブジェクトです。

しかし、不変構造も良好にサポートしています。すべての不変のバージョンを持っている不変コレクションAPIはありません:

scala> val a = Vector(1,1,1) // note the "scala.collection.immutable namespace" 
a: scala.collection.immutable.Vector[Int] = Vector(1, 1, 1) 

scala> val b = a // not a deep copy, but a shared ref to an immutable object 
b: scala.collection.immutable.Vector[Int] = Vector(1, 1, 1) 

// mutating operations on immutable objects will return a modified 
// copy, leaving the origin object unchanged 
scala> b.updated(1, 2) 
res0: scala.collection.immutable.Vector[Int] = Vector(1, 2, 1) 

scala> b 
res1: scala.collection.immutable.Vector[Int] = Vector(1, 1, 1) 

scala> a 
res2: scala.collection.immutable.Vector[Int] = Vector(1, 1, 1) 

scala> val c = b.updated(1, 2) 
c: scala.collection.immutable.Vector[Int] = Vector(1, 2, 1) 

ごく稀に、私は本当にオブジェクトではなく、深いコピーへの参照を渡したいです。

Scalaと他のcファミリ言語では、 "R"のようにディープコピーは使用しません。常に守備的なコピーを取るよりも参照を渡す方が効率的です。オブジェクトが不変の場合、コピーは読み取り時ではなく書き込み時にのみ必要です。

関連する問題