Blog coding and discussion of coding about JavaScript, PHP, CGI, general web building etc.

Wednesday, August 31, 2016

Understanding passing by value vs. reference in this Ruby example

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 by michau for Understanding passing by value vs. reference in this Ruby example


It actually has nothing to do with passing parameters to methods. I extracted important parts from your examples:

baz = 'value'  bar = baz  bar = 'reference'  puts baz  bar = baz  bar.replace 'reference'  puts baz  

You may think of variables as pointers. When you use =, you make a variable point to something different, and the original value remains unchanged, and can be accessed through other variables that point at it. But when you use replace, you change the content of the string the variable points at.

Answer by Dave Schweisguth for Understanding passing by value vs. reference in this Ruby example


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.

Answer by Maxim Pontyushenko for Understanding passing by value vs. reference in this Ruby example


In first case you use bar = 'reference' which creates new object. In second one .replace changes the object you apply it to. You can ensure this by .object_id method. For example:

def foo_eql(bar)    bar = 'reference'    puts bar.object_id    bar  end    def foo_replace(bar)    bar.replace 'reference'    puts bar.object_id    bar  end    baz = 'value'  puts baz.object_id #Here you will get original baz object_id  res1 = foo_eql(baz) #Here you will get printed new object_id  res2 = foo_replace(baz) #Here you will get printed original baz object_id  puts "foo_eql: Ruby is pass-by-#{res1}"  => foo_eql: Ruby is pass-by-reference  puts "foo_replace: Ruby is pass-by-#{res2}"  => foo_replace: Ruby is pass-by-reference  

So there is no magic at all. In your example with hashes you do not create new Hash object but modify existing one. But you can create new one with method like this:

def my_foo(a_hash)    a_hash = a_hash.merge({"test" => "reference"})  end  my_foo(hash)  puts "Ruby is pass-by-#{hash["test"]}"  

Basically you pass the reference to an object in "value" way. For better understanding check this post and comments to it.

Answer by Fran Martinez for Understanding passing by value vs. reference in this Ruby example


Very interesting thing.

Play with the object_ids, you will see what ruby is doing bellow the scenes:

def foo(bar)    puts bar.object_id    bar = 'reference'    puts bar.object_id  end    baz = 'value'  puts baz.object_id  foo(baz)  

Output

> baz = 'value'  => "value"    > puts baz.object_id  70241392845040    > foo(baz)  70241392845040  70241392866940  

After the local assign bar = 'reference', the local variable bar will reference another object, so it won't change the original one.

It seems that in some cases it will make a dup of your object.

Answer by maicher for Understanding passing by value vs. reference in this Ruby example


Maybe this will help to understand it:

x = 'ab'  x.object_id  => 70287848748000 # a place in memory    x = 'cd'  x.object_id  => 70287848695760 # other place in memory (other object)    x.replace('xy')  x.object_id  => 70287848695760 # the same place in memory (the same object)  


Fatal error: Call to a member function getElementsByTagName() on a non-object in D:\XAMPP INSTALLASTION\xampp\htdocs\endunpratama9i\www-stackoverflow-info-proses.php on line 72

0 comments:

Post a Comment

Popular Posts

Powered by Blogger.