bobito
bobito

Reputation: 31

ruby unintended variable assignment/change

i'm quite a layman in programming and a noob to ruby but find it useful for my work anyway. Cuirrently I work on a rather large script which brought the following unintended effect:

def my_reduce_method(value_hash,some_keys)
  value_hash.delete(some_keys) 
end

puts all_values
=> all_values

some_values = all_values # start my block with all values (class: hash)

some_values = my_reduce_method(some_values,keys_to_reduce) 
# here only some_values should be effected!

puts all_values
=> some_values

Right in the block there is no damage, but the original all_values is lost! How can I ensure that in a certain code block a certain variable is definitely not changed?

Thank you in advance for any input!!!

Upvotes: 1

Views: 135

Answers (2)

bertramscharpf
bertramscharpf

Reputation: 323

Object#clone preserves the frozen attribute and singleton methods. If you don't need those, what happens to your example, Object#dup is sufficient.

Upvotes: 0

jaeheung
jaeheung

Reputation: 1208

All object assignments in Ruby are reference assignments.

That means, when you do:

some_values = all_values

You're copying the reference(or address) of the object which all_values is referencing(or pointing).

The solution for your case is simple:

some_values = all_values.clone

.dup also works usually (can be different depending on the object).

Another thing to be careful about is, when all_values[:x] has a string and you do:

some_values = all_values.clone
some_values[:x] += 'abc'

This will not change all_values[:x] because some_values[:x] gets (is assigned) a new string object.

But if you do:

some_values = all_values.clone
some_values[:x] << 'abc'

Both all_values[:x] and some_values[:x] change, because they both reference the same string object.

This is the effect of the shallow copy @Plasmarob mentioned.

Upvotes: 1

Related Questions