Question

Is this behavior correct? I'm running some code like the following:

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

At the end of all that, x's value has been changed as expected but so has the value for @a_hash. I'm getting {:a => 1, :b => 2} as the value for both of them. Is this normal behavior in Ruby?

Was it helpful?

Solution

Yes, instance variable @a_hash and local variable x store the reference to the same Hash instance and when you change this instance (using mutator method merge! that change object in place), these variables will be evaluated to the same value.

You may want to use merge method that create a copy of the object and don't change original one:

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

OTHER TIPS

@a_hash is link to x. So if You want @a_hash not changed, you should do like this:

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

Yes, that's normal behavior in ruby (and most other languages). Both x and @a_hash are references to the same object. By calling merge! you change that object and that change in visible through all variables that refer to it.

If you don't want that behavior, you should either not use mutating methods (i.e. use x = x.merge(...) instead) or copy the object before you mutate it (i.e. x = @a_hash.dup).

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top