In ruby, just about every object is passed by reference. This means when you do something as simple as
a = b
unless a was one of the simple types, after this assignment a
and b
will point to the same thing.
This means if you alter the second variable, the first is affected the same way:
irb(main):001:0> x = "a string"
=> "a string"
irb(main):002:0> y = x
=> "a string"
irb(main):003:0> x[1,0] = "nother"
=> "nother"
irb(main):004:0> x
=> "another string"
irb(main):005:0> y
=> "another string"
irb(main):006:0>
and of course the same applies for hashes:
irb(main):006:0> a = { :a => 1 }
=> {:a=>1}
irb(main):007:0> b = a
=> {:a=>1}
irb(main):008:0> a[:b] = 2
=> 2
irb(main):009:0> a
=> {:a=>1, :b=>2}
irb(main):010:0> b
=> {:a=>1, :b=>2}
irb(main):011:0>
If you don't want this to happen, use .dup
or .clone
:
irb(main):001:0> a = "a string"
=> "a string"
irb(main):002:0> b = a.dup
=> "a string"
irb(main):003:0> a[1,0] = "nother"
=> "nother"
irb(main):004:0> a
=> "another string"
irb(main):005:0> b
=> "a string"
irb(main):006:0>
For most people dup
and clone
have the same effect.
So if you write a function that modifies one of its parameters, unless you specifically want those changes to be seen by the code that calls the function, you should first dup the parameter being modified:
def test_111(hash)
hash = hash.dup
# etc
end
The behavior of your code is called a side effect - a change to the program's state that isn't a core part of the function. Side effects are generally to be avoided.