bill bill - 3 months ago 8
Ruby Question

Understanding passing by value vs. reference in this Ruby example

After reading Is ruby pass by reference or value? I have learned a lot, but I am left with more questions than I had before reading it (which I suppose is good).

Consider the following example

def foo(bar)
bar = 'reference'
end
baz = 'value'
foo(baz)
puts "Ruby is pass-by-#{baz}"


Output
Ruby is pass-by-value


Here is my attempt to dissect how this works:

First, in the global scope
baz
has the value
value
.

Now
foo
takes a parameter, whatever you pass into it, is on a
local
level.

Therefore when we pass
baz
in, there is ANOTHER
baz
that is equal to
reference
but this is on the local level, as a result, when we puts this on a global level it prints
value
.

Now consider another example

def foo(bar)
bar.replace 'reference'
end
baz = 'value'
foo(baz)
puts "Ruby is pass-by-#{baz}"


Output

Ruby is pass-by-reference


If what I said above is true, does the
.replace
method here change the global
baz
? Am I interpreting this correctly? Please feel free to point out any mistakes in my attempts, I have no clue if im on the right track.

Thanks!

EDIT

More Magic

def my_foo(a_hash)
a_hash["test"]="reference"
end;

hash = {"test"=>"value"}
my_foo(hash)
puts "Ruby is pass-by-#{hash["test"]}"

Answer

Ruby is pass-by-value, but the values are references to objects.

In your first experiment, baz is a reference to the string "value". bar is initialized to a copy of baz (that is, a copy of the reference) when you call foo. You then overwrite bar with a reference to the string "reference". Since bar is a copy, overwriting it doesn't change baz.

In your second experiment, again, baz is a reference to the string "value" and bar is initialized to a copy of baz when you call foo. This time you don't overwrite bar, but call a method on it. Although bar is a copy of baz, they refer to the same object (the string "value"). Calling the method changes the state of that object. You then call to_s on baz (indirectly, by substituting it into "Ruby is pass-by-#{baz}"), and to_s returns the new state.

Your third experiment is a lot like the second. In the method, you change the state of the object referred to by the copy of the reference, then, outside the method, you read the new state back through the original reference.

Comments