2012-02-03 4 views
0

この動作は正しいですか?私は、次のようないくつかのコードを実行している:ハッシュマージの動作

@a_hash = {:a => 1} 
x = @a_hash 
x.merge!({:b => 2}) 

をすべてのことの終わりには、Xの値が予想されるように変更したがそう@a_hashの値を持ってきました。私は両方の値として{:a => 1、:b => 2}を得ています。 Rubyではこれが正常な動作ですか?

答えて

4

はい、インスタンス変数同じHashインスタンスへの参照、あなたは、このインスタンスを変更する場合(所定の位置にオブジェクトを変更するミューテータメソッドmerge!を使用して)は、これらの変数が同じ値に評価されます@a_hashとローカル変数x店。

@a_hash = {:a => 1} 
x = @a_hash 
y = x.merge({:b => 2}) 
# y => {:a => 1, :b => 2} 
# x and @a_hash => {:a => 1} 
+0

ああ、大丈夫です。私はそれが起こっていると思った。ありがとう。 – blim8183

2

@a_hashは、Xへのリンクです:

あなたは、オブジェクトのコピーを作成し、オリジナルのものを変更しないmerge方法を使用することをお勧めします。あなたが変更されていない@a_hashたいのであれば、あなたは次のように実行する必要があります。

@a_hash = {:a => 1} 
x = @a_hash.clone 
x.merge!({:b => 2}) 
+2

'x = @ a_hash.merge(:b => 2)'と完全に同等である場合はクローン化することをお勧めしません。 – tokland

1

はい、それはルビー(および他のほとんどの言語)での正常な動作です。 x@a_hashは同じオブジェクトへの参照です。 merge!を呼び出すと、そのオブジェクトが変更され、そのオブジェクトを参照するすべての変数を通じてその変更が表示されます。

このような動作をしたくない場合は、突然変異するメソッド(代わりにx = x.merge(...)を使用)を使用するか、オブジェクトを変更する前にコピーしてください(例:x = @a_hash.dup)。