1

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!!!

7
  • Nothing in the code you posted will modify all_values, so I'm guessing something in my_reduce_method is modifying it. Commented Nov 14, 2013 at 17:50
  • It's a shallow copy of all_values. That's the problem. my_reduce_method is modifying some_values, which is pointing to the same data that all_values points to. Commented Nov 14, 2013 at 17:53
  • 1
    There was no good reason for the downvote. Most appropriate question from first-time poster I've seen. Commented Nov 14, 2013 at 17:58
  • @Plasmarob, and, as usual, no explanation/justification provided for the downvote. Commented Nov 14, 2013 at 18:20
  • 2
    An easy way to make of a deep copy of any object o that can be dup'ed: Marshal.load(Marshal.dump(o)). Commented Nov 14, 2013 at 18:28

2 Answers 2

1

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.

Sign up to request clarification or add additional context in comments.

11 Comments

Strings are references too.
How kind of you to credit. Someday I'd like to see SO implement a clean interface for people to merge their answers and ownership.
Ditto, ditto, and ditto.
@Plasmarob My point is, .clone and .dup also make shallow copies. Thanks for the kind comment though.
@jaeheung: Strings are mutable and as such aren't copied when you assign them to a variable. They just get a new reference. Both variables then point to the same String object (as verified by its object_id)
|
0

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.