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:

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:

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:

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:

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

40 Replies to “Ruby, pass by value or by reference?”

  1. 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. 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. 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. 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. @ 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. 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. 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…

  8. 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.“.

  9. 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

  10. The code snippet should have looked like this:


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

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

  12. 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

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

  14. @ 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.

  15. @ 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.

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

  17. @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.

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

    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:

    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

  19. @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

  20. 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.

  21. 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

  22. @taelor, I tried the following statement on Ruby 1.8.6

    Which is totally different from Ruby 1.9.1

    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?

  23. 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)

  24. 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]

  25. #!/usr/bin/ruby
    def foo(bar)
    puts “bar inspect: #{bar.object_id.to_s(16)}”
    end
    buh = { :abc => “def” }
    puts ” buh inspect: #{buh.object_id.to_s(16)}”
    foo(buh)

    🍺 ./test.rb
    buh inspect: 3ff0020837ac
    bar inspect: 3ff0020837ac

Leave a Reply

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