21 Apr, 2009 in Ruby by khelll

Ruby, pass by value or by reference?

It’s a basic question that I myself had a problem with when i started using Ruby: Does Ruby pass by value or by reference?
Well, if you want a direct answer, then: Ruby passes by value. It’s a similar behavior of what Java does.

Let’s prove it via examples:
Update: this example was passing integers, and it turned out that even everything in ruby is an object, but immedaite values are passed directly by their values, so i changed this example to let it pass strings instead.

Let’s pass an argument to a method and check what goes on:

irb(main):003:0> def change(x); x = '10'; end
=> nil
irb(main):004:0> y = '3'; puts change(y) ,  y
'10'
'3'
=> nil

As you see, we defined a method ‘change’ that takes a parameter ‘x’, changes it value and then returns it back. Then we invoked that method on the argument ‘y’ which had the value ‘3′, and kept having the same value after the method invocation.
This simple example proves that the argument is not passed by reference, otherwise the value of ‘y’ would rather changed to ‘10′ after the method invocation.

Now let’s take another example:

irb(main):005:0> def another_change(x); x[0] = 'f'; x; end
=> nil
irb(main):006:0> s = "hello"; puts another_change(s) , s
fello
fello
=> nil

In this example, the passed argument value ‘hello’ has changed to ‘fello’, and thus it proves that the argument is not passed by value, otherwise the value of ’s’ would kept having the same value ‘hello’.

Thus it’s not by value, neither by reference, then what is it?

As you know, everything in Ruby is an object, and thus, doing:

value = "smthin"

means: assign a reference(a place in memory that points to referenced value. In other words, it’s a place that holds the memory address of the referenced value) of the string ’somthin’ to the variable named ‘val’, and normally when working with the variable ‘val’, it means we are working on it’s referenced object ’smthing’.

But when invoking a method:

Foo(val)

Things change a bit, as Ruby passes a copy of the ‘val’ reference itself(which is the memory address of the referenced object), not it’s referenced object, to the method Foo, and that copy will still reference the same object ’smthing’ as the variable ‘val’ does.
This is called: Pass by Value, a copy of a reference to an object is passed, and so, not the referenced object itself is passed, neither the argument itself.
Then Ruby passes by value. Some ppl like to call it “pass by reference value”, but that’s not standard afaik.

That explains what goes in both examples, as in the first example the value of the argument ‘y’ didn’t change due to the fact that we are not passing the reference ‘y’ itself, instead a copy of it, and thus, when its copy referenced another object(via assignment operator), the original variable ‘y’ kept referencing it’s object, the object with value ‘3′ in our case. As for the second example, the argument ’s’ changed due to the fact that its passed copy is still referencing the same object ‘hello’, but the operator [] changed the referenced object value, and thus got a new value ‘fello’.

I hope the idea is clear now, if not, please don’t hesitate to comment.

Update:
I have blogged a new article explaining passing by reference and value in 3 languages c++, java and ruby

36 Responses so far | Have Your Say!

  1. Moski - Gravatar

    Moski  |  April 21st, 2009 at 2:42 am #

    The way i think about, Objects or at least the stuff that looks like objects are passed by reference … meaning, Stuff that u intilize like an object ( Array.new , String.new …) are passed by ref , while other stuff are passed by value …. (int, doubles) …

    This keeps my head straight without jumping deep into the technicality behind it. Its a great post khalid, thanx alot.

    One thing to note, In the post you defined the value “value” but keept accessing it as val , i though i missed the definition of val somewhere but i guess u were talking about the same variable.

  2. dohzya - Gravatar

    dohzya  |  April 21st, 2009 at 2:53 am #

    Ruby uses the “pass by reference” version.
    In your first example, you have *not* changed the “variable” x, you have create a new object and your local pointer x now refers this new object. So the global x still refers to the old object.

    see: http://www.ruby-forum.com/topic/41160

  3. dohzya - Gravatar

    dohzya  |  April 21st, 2009 at 2:55 am #

    All objects are passed by reference.

    x = 10 *don’t change* x, because x is not a variable, it’s only a pointer.
    So x = 10 affects the local pointer x to the new object 10.
    So it’s normal that the global pointer x still refers to the object 3 ;)

    see: http://www.ruby-forum.com/topic/41160

  4. dohzya - Gravatar

    dohzya  |  April 21st, 2009 at 3:06 am #

    Ruby only pass by references.
    There is neither variable nor value in ruby, only objects and pointers.
    “x = 10″ make the local pointer x referring the object 10, so the global pointer x still refers to the object 3.

  5. khelll - Gravatar

    khelll  |  April 21st, 2009 at 3:43 am #

    @ moski, i just was trying to explain this detail you are talking about, since everything is an object, even the ‘primitive’ types, then the passed arguments are copies of the the main references, which said to be passed by value.

    And thanks for the value note, i have updated it.

  6. jds - Gravatar

    jds  |  April 21st, 2009 at 3:54 am #

    dohzya,

    Ruby passes by value. Pass-by-Reference would mean that you would be able to change what the variables passed to the method would point to. You can do this in C and C++ with the & operator. Ruby (and Java) have no equivalent. Under the hood, the ‘value’ that is passed is the pointer to the object, which is why people tend to think it’s passed by reference and that’s confusing.

    Run the following code in irb and it should illustrate what I mean.


    def foo(bar)
    bar = "if you can see this, bar was passed by reference"
    end

    message = "if you can see this, it was passed by value"
    foo(message)
    puts(message)

    If Ruby passed by reference then the object pointed to by ‘message’ would have changed.
    This isn’t the case.

  7. Osama - Gravatar

    Osama  |  April 21st, 2009 at 4:06 am #

    where is my comment?!!

  8. dohzya - Gravatar

    dohzya  |  April 21st, 2009 at 4:18 am #

    I think the “pass by reference” or the “pass by value, when value is a pointer” are identical.

    This is a philosophical question, and the philosophy of ruby is “there is no variable, just names allowing to act with objects”

    so “bar” and “bar =” are nothing else than changing the object referenced by the name, unless they are equivalent for “self.bar” and “self.bar=”, which are methods…

    def foo(bar)
    bar.replace(“if you can see this, bar was passed by reference”)
    end

    here the object is changed, which is impossible in a “pass by value, when value is not a pointer” way…

  9. Osama - Gravatar

    Osama  |  April 21st, 2009 at 4:47 am #

    I am posting my comment again:
    I agree with dohzya, ruby does not pass by value. it all depends on the object identity and how you use it.

    check out http://www.ruby-doc.org/core-1.9/classes/Fixnum.html which state:
    “Fixnum objects have immediate value. This means that when they are assigned or passed as parameters, the actual object is passed, rather than a reference to that object. Assignment does not alias Fixnum objects. There is effectively only one Fixnum object instance for any given integer value, so, for example, you cannot add a singleton method to a Fixnum.“.

  10. jds - Gravatar

    jds  |  April 21st, 2009 at 5:00 am #

    dohzya.

    You may think that, but you’d be incorrect. Pass-by-value and pass-by-reference have different semantics and if one thinks, ‘pass by reference’ or ‘pass by value, when value is a pointer’ are identical’ then it is clear that one does not understand the difference. My example was bad, so I’ll try to explain again.

    In this code, “hello 1!” will be output, BUT it does not imply pass by reference. (It was based on my crappy example, so I blame myself…).

    Think if it like this. ‘message’ is a variable which contains a VALUE and that value is a POINTER to an object of type String.

    Pass-by-value means that ‘foo’ sees bar as holding the same VALUE as ‘message’. And that value is the pointer to a string.

    If Ruby used pass-by-reference, in method ‘foo’, the parameter ‘bar’ would contain the pointer to the memory location occupied by the VARIABLE ‘message’ (another level of indirection).

    So the code below does not show that Ruby uses pass-by-reference. All it demonstrates is that methods can be called on objects passed to a method. Languages would pretty dull if you couldn’t do that. ‘replace’ changes the contents of the object pointed to by ‘message’. ‘message’ is still the same object. Again, if Ruby allowed pass by reference, you’d be able to point ‘message’ at another object. Not possible in Ruby.


    def foo(bar)
    bar.replace("hello 2!")
    end

    message = "hello 1!"
    foo(message)
    puts message

  11. jds - Gravatar

    jds  |  April 21st, 2009 at 5:02 am #

    The code snippet should have looked like this:


    def foo(bar)
    bar.replace("hello 2!")
    end
    message = "hello 1!"
    foo(message)
    puts message

  12. dohzya - Gravatar

    dohzya  |  April 21st, 2009 at 5:20 am #

    Ok, if I understand, I confused pass-by-reference and pass-by-copy-of-reference (which is a pass-by-value).

  13. Diego Scataglini - Gravatar

    Diego Scataglini  |  April 21st, 2009 at 5:25 am #

    Sorry guys but dohzya has it right.
    It’s always by reference. The confusion that you guys are experiencing is due to the local scope of the variable names.
    When you assign a new variable to the variable you’re doing so in the local scope.
    You are changing the pointer of the local variable to a new reference.
    Furthermore the first example is fubar because Integers are immutable. You can’t do 1 += 2
    They are the worst type to use for demonstrate by val vs by ref.
    Here is a good example for you

    class A
    attr_accessor :b
    end

    class B
    end

    def change_A x
    x.b = 1
    end

    def change_locally x # => locally named variable now pointing to passed reference
    x = B.new # => local variable now pointing to something new
    end

    a = A.new
    puts change_A(a)
    puts a
    puts change_locally(a)
    puts a

  14. jds - Gravatar

    jds  |  April 21st, 2009 at 5:25 am #

    dohzya, that’s correct. The terminology is confusing. The value being passed is the pointer in Ruby, not the pointer to the variable containing the pointer.

    The only reason I remember this, is because I was asked in a job interview years ago and it completely tripped me up. If I had come from a C or C++ background, I would have remembered!

  15. Diego Scataglini - Gravatar

    Diego Scataglini  |  April 21st, 2009 at 5:28 am #

    Ok the code doesn’t look right in here.
    Here is in a gist http://gist.github.com/99137

  16. khelll - Gravatar

    khelll  |  April 21st, 2009 at 5:35 am #

    @ dohzya, the point is that, passing a pointer is not considered to be passing by reference, cause the pointer value will be copied (in stack frame), and whatever the pointer points to, when assigned to another object, it won’t affect the argument passed to the method, which will keep holding the same value,before and after the method invocation.

    The mistake most of programmers have is that they think if the object is being modified then it’s being passed by reference, which is not totally true, as it might be passed by value of reference, which is our case here, and thus you still can edit the object.

    To say it’s passed by reference you should be able to change the argument that was passed, and let it have another value from inside the invoked method.

  17. jds - Gravatar

    jds  |  April 21st, 2009 at 5:51 am #

    Here is a thread that more than amply demonstrates the confusion that can occur when discussing this topic: http://www.ruby-forum.com/topic/41160

    Diego: look at my gist: http://gist.github.com/99146 and try to implement ‘foo’ in such a way as to demonstrate that Ruby can pass by reference.

    Khelll: you do a better job of explaining than I do!

  18. khelll - Gravatar

    khelll  |  April 21st, 2009 at 6:12 am #

    @ Osama , if that is the case, then you are supporting my theory:

    Fixnum objects have immediate value. This means that when they are assigned or passed as parameters, the actual object is passed,rather than a reference to that object.

    This indicates that it’s passed by value, and it seems logical as immediate values will have 4 bytes (or less long), same as the size of the reference, so instead of passing references they pass it by value.

    However, please note that the references mentioned here are pointers, and passing pointers doesn’t mean passing by reference.

    I hope you can read other replies to get the answer, if you still not contented, I’ll explain more.

  19. khelll - Gravatar

    khelll  |  April 21st, 2009 at 6:17 am #

    @ Diego Scataglini, answering jds question will help you clarify the point, check this pastie please.

    Thanks

  20. khelll - Gravatar

    khelll  |  April 21st, 2009 at 6:18 am #

    @jds, that was a generous effort of you to help clarify it.

    Thanks a lot

  21. jds - Gravatar

    jds  |  April 21st, 2009 at 6:24 am #

    @Khelll Heh, no worries. It was a welcome distraction from filling in my Australian visa application forms…

  22. andres - Gravatar

    andres  |  April 21st, 2009 at 6:52 am #

    variable scope, dude

  23. Osama - Gravatar

    Osama  |  April 21st, 2009 at 7:03 am #

    @khell: well, 1st: my comment came too late the time I sent it. 2nd: if you gave this article to some newbie ruby developer; she will be confused as hell.

    3rd: I am not with or against your theory, since this is not a theory, is it? ;-) I was taking your attention to a point that you didn’t mentioned in your article – simple, direct and short.

  24. Diego Scataglini - Gravatar

    Diego Scataglini  |  April 21st, 2009 at 7:11 am #

    Khell, again the problem is scope.
    Without reflection magic you can’t overwrite a globally scoped named variable, you can only change it like in my change_A example

    how about this

    a = [1]
    def foo x
    x << 2
    end
    foo a
    puts a

    or the answer applied to jds challenge http://gist.github.com/99182

  25. khelll - Gravatar

    khelll  |  April 21st, 2009 at 7:55 am #

    @ Diego Scataglini , i’ll start with your last example:

    a = [1]
    def foo x
    x << 2
    end
    foo a
    puts a

    if i got you exactly, then you are saying that object ‘a’ is passed by reference, and that’s why it’s being changed(correct me if i’m mistaken). Ok if that’s what you are saying, then again it’s not passed by reference, instead this is called pass by (reference) value, and that’s why you are able to change it. to make things simpler: look at this example:

    irb(main):038:0> v = [5]
    => [5]
    irb(main):039:0> v.object_id
    => -604097178
    irb(main):040:0> def change(x); x << 10; end
    => nil
    irb(main):041:0> change v
    => [5, 10]
    irb(main):042:0> v.object_id
    => -604097178

    Can you provide me with any method that changes the value of object_id for the ‘v’ variable (without reflection)?

    Passing by reference means that you can make the passed argument reference another object , and so, you get another object_id, after the method invocation.

    If you are wondering how you are able to change the object without you pass by reference, then please look again at this comment

  26. Scott Olmsted - Gravatar

    Scott Olmsted  |  April 21st, 2009 at 11:36 am #

    Maybe this code will be a better example to work with:


    a = [1]
    b = [1]
    def foo x, y
    x = [2]
    y << 2
    end

    foo a, b
    puts a.inspect
    puts b.inspect

  27. khelll - Gravatar

    khelll  |  April 21st, 2009 at 11:49 am #

    @ scott, what is your point?

  28. jds - Gravatar

    jds  |  April 22nd, 2009 at 12:06 am #

    @Diego

    All your gist does is prove that you can manipulate an object when passing said object as a parameter to a method. It does not change what the variable object points to. Look up (pass/call)-by-reference on wikipedia, and perhaps you will get a better idea of what pass-by-reference means. When you understand what it means, then perhaps we can argue about whether or not Ruby supports it.

    If Ruby supported pass-by-reference then this could work:


    def swap(a,b)
    a,b = b,a
    end
    foo = 1
    bar = 2
    # notice that we are not capturing a return value because we
    # wouldn't need to if Ruby used pass-by-reference.
    swap(foo,bar)
    puts foo # 2
    puts bar # 1

  29. C++ passes by reference, Java and Ruby don’t – Khaled alHabache’s official blog - Gravatar

    C++ passes by reference, Java and Ruby don’t - Khaled alHabache’s official blog  |  April 22nd, 2009 at 12:17 am #

    [...] got a lot of comments for the previous article, that was explaining how Ruby passes by value, just like Java [...]

  30. khelll - Gravatar

    khelll  |  April 22nd, 2009 at 12:24 am #

    Update:
    I have blogged a new article explaining passing by reference and value in 3 languages c++, java and ruby

  31. Kadom - Gravatar

    Kadom  |  April 22nd, 2009 at 11:03 am #

    bar = “if you can read this bar was passed by value”

    def foo(bar)
    bar.replace “if you can see this, bar was passed by value reference”
    end

    foo(bar)

    puts bar

    Saying that b is passed by value is as incorrect as saying that b is passed by reference. I am able to change bar via the parameter bar. That means that I do have a reference to bar in some sense. If what i received was simply a value copy, then I would not be able to reach the outer scope bar. if it was an actual pointer to bar, then I would be able to simply manipulate it as I do in C/C++. I understand the argument about the object_id, but claiming ruby is simply pass by value misses an important distinction. I was able to alter bar within foo when bar was passed as a parameter.

  32. khelll - Gravatar

    khelll  |  April 22nd, 2009 at 11:21 am #

    @kadom, what is being passed is a value of a copied reference, that’s called pass by reference value or pass by value simply.

  33. Ennuyer.net » Blog Archive » I am way behind on my rails link blogging. Link dump and reboot. - Gravatar

    Ennuyer.net » Blog Archive » I am way behind on my rails link blogging. Link dump and reboot.  |  May 9th, 2009 at 2:45 am #

    [...] Ruby, pass by value or by reference? – Khaled alHabache’s official blog [...]

  34. AndrewBoldman - Gravatar

    AndrewBoldman  |  June 4th, 2009 at 5:26 am #

    Hi, cool post. I have been wondering about this topic,so thanks for writing.

  35. taelor - Gravatar

    taelor  |  November 3rd, 2009 at 6:27 pm #

    Hey, khell, its been awhile since I visited your site. Just wanted to show you something along these lines of pass-by-x. check out this gist and run it in ruby 1.8.7 vs 1.9.1, you get totally different outputs. I think that the 1.9 is pass by reference in this case.

    http://gist.github.com/225709

  36. khelll - Gravatar

    khelll  |  November 5th, 2009 at 3:23 pm #

    @taelor, I tried the following statement on Ruby 1.8.6

    { :some_id => 1, :something => 'one' }.reject{|k, v| k =~ /_id/ }
    #=> {:some_id=>1, :something=>"one"}

    Which is totally different from Ruby 1.9.1

    { :some_id => 1, :something => 'one' }.reject{|k, v| k =~ /_id/ }
    #=> {:something=>"one"}

    If you just make it k.to_s, your gist will give the same result on both versions of Ruby.
    On the other hand, I can’t see where pass by reference is taking place…. can you elaborate?

Leave a Feedback

XHTML: You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre lang="" line="" escaped="">