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

This entry was posted in Ruby and tagged , . Bookmark the permalink.

38 Responses to Ruby, pass by value or by reference?

  1. Moski says:

    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 says:

    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 says:

    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 says:

    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 says:

    @ 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 says:

    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 says:

    where is my comment?!!

  8. dohzya says:

    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 says:

    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 says:

    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 says:

    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 says:

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

  13. 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 says:

    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. Ok the code doesn’t look right in here.
    Here is in a gist http://gist.github.com/99137

  16. khelll says:

    @ 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 says:

    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 says:

    @ 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 says:

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

    Thanks

  20. khelll says:

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

    Thanks a lot

  21. jds says:

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

  22. andres says:

    variable scope, dude

  23. Osama says:

    @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. 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 says:

    @ 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. 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 says:

    @ scott, what is your point?

  28. jds says:

    @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. Pingback: C++ passes by reference, Java and Ruby don’t - Khaled alHabache’s official blog

  30. khelll says:

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

  31. Kadom says:

    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 says:

    @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. Pingback: Ennuyer.net » Blog Archive » I am way behind on my rails link blogging. Link dump and reboot.

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

  35. taelor says:

    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 says:

    @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?

  37. Black_crown says:

    As i read above …my curiosity asking a question to me.May be its stupid but i dare to ask to you.i am a newbie to ruby with strong background of .net, i found some new in ruby which is not possible in some other as i know. so here the question is
    i defined a method which taking one parameter ,

    def dummy_method(valued)
    some_thing=valued
    return some_thing
    end

    now on the call of this method
    dummy_method(valued=gets.chomp.to_i) #that is a normal call

    but can i do like this to call

    dummy_method(valued= print ” Enter your value” ,gets.chomp.to_i)

  38. antan says:

    I think this is what happens:

    b=5 #<= b points to an object 5

    def test(a) #<= a points to the same object as b (5)
    a=6 #<= a points to a new object 6
    end

    test(b) #<= returns 5

    —————————-
    b=[1,2,3]

    def test2(a) #<= a points to the same object as b ([1,2,3])
    a[0]=6 #<= a[0], which pointed to the first object in the array (1), now points to the new object 6
    end

    test2(b) #<= returns [6,2,3]

Leave a Reply

Your email address will not be published. Required fields are marked *

*

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