@user.update_languages(params[:language][:language1], 
                       params[:language][:language2], 
                       params[:language][:language3])
lang_errors = @user.errors
logger.debug "--------------------LANG_ERRORS----------101-------------" 
                + lang_errors.full_messages.inspect

if params[:user]
  @user.state = params[:user][:state]
  success = success & @user.save
end
logger.debug "--------------------LANG_ERRORS-------------102----------" 
                + lang_errors.full_messages.inspect

if lang_errors.full_messages.empty?

@user object adds errors to the lang_errors variable in the update_lanugages method. when I perform a save on the @user object I lose the errors that were initially stored in the lang_errors variable.

Though what I am attempting to do would be more of a hack (which does not seem to be working). I would like to understand why the variable values are washed out. I understand pass by reference so I would like to know how the value can be held in that variable without being washed out.

upvote
  flag
I also notice that I am able to retain that value in a cloned object – Sid
1 upvote
  flag
You should look at Abe Voelker answer. But after running around the block on this, here's how I would say it. when you pass an object Foo to a procedure, a copy of the reference to the object is passed, bar, Pass by value. you cannot change the object that the Foo points to, but you can change the contents of the object that it points to. So if you pass an array, the contents of the array can be changed, but you cannot change what array is being referenced. nice to be able to use the methods of Foo without having to worry about messing up other dependencies on Foo. – bobbdelsol

12 Answers 11

up vote 205 down vote accepted

In traditional terminology, Ruby is strictly pass-by-value. But that's not really what you're asking here.

Ruby doesn't have any concept of a pure, non-reference value, so you certainly can't pass one to a method. Variables are always references to objects. In order to get an object that won't change out from under you, you need to dup or clone the object you're passed, thus giving an object that nobody else has a reference to. (Even this isn't bulletproof, though — both of the standard cloning methods do a shallow copy, so the instance variables of the clone still point to the same objects that the originals did. If the objects referenced by the ivars mutate, that will still show up in the copy, since it's referencing the same objects.)

upvote
  flag
Thank you. I'm still not sure if this is completely a good feature. Wouldn't an explicit method to pass by value be helpful though everything is an object. Another thing is I find that the cloned copy has a different object_id so doesn't that make it completely indifferent to the original object though it may hold the values of the original object or are my fundamentals totally flawed here? – Sid
3 upvote
  flag
Yes, the clone is a completely independent object. As for pass-by-value, it's not really compatible with pure OO, where "values" don't exist except as object state. The closest you could get is something like Objective-C's bycopy type modifier that tells the runtime to make a copy behind the scenes. That does sound useful. – Chuck
upvote
  flag
Thanks chuck that what was really useful.Thanks again – Sid
68 upvote
  flag
Ruby is pass-by-value. No ifs. No buts. No exceptions. If you want to know whether Ruby (or any other language) is pass-by-reference or pass-by-value, just try it out: def foo(bar) bar = 'reference' end; baz = 'value'; foo(baz); puts "Ruby is pass-by-#{baz}". – Jörg W Mittag
74 upvote
  flag
@JörgWMittag: Yeah, but the OP's confusion is actually not pass-by-value or pass-by-reference in the strict CS sense of the words. What he was missing is that the "values" you're passing are references. I felt that just saying "It's pass-by-value" would be pedantic and do the OP a disservice, as that isn't actually what he meant. But thanks for the clarification, because it is important for future readers and I should have included it. (I'm always torn between including more info and not confusing people.) – Chuck
upvote
  flag
In this answer, what does "ivars" mean? – Eddified
upvote
  flag
@Eddified: Instance variables. I didn't think it had any other meaning. – Chuck
11 upvote
  flag
Disagreeing with @Jorg. Ruby is pass by reference, he just changes the reference. Try this instead: def foo(bar) bar.replace 'reference' end; baz = 'value'; foo(baz); puts "Ruby is pass-by-#{baz}" – pguardiario
3 upvote
  flag
@pguardiario: Your code has absolutely nothing whatsoever to do with passing by reference or passing by value. It would print exactly the same thing regardless of whether Ruby is pass-by-reference or pass-by-value. The only thing your code proves is that Ruby is not a purely functional language, which I don't think anybody would dispute anyway. – Jörg W Mittag
upvote
  flag
I disagree. Not worth belaboring the point however. – pguardiario
2 upvote
  flag
@pguardiario: The thing about "pass-by-reference" vs. "pass-by-value" is that pass-by-reference means you're directly referring to the caller's memory space, such that reassigning the variable would change the variable in the caller. This doesn't happen. foo's variable bar is an independent variable that simply has the same value as the caller's baz. It just so happens that in this case the value is an object reference. But in terms of calling convention, it's considered pass-by-value. – Chuck
upvote
  flag
@Chuck, I disagree. foo's bar is a variable that references the original object. Otherwise the original object couldn't be affected from inside the method. That's why I say pass by reference. Though I will concede that it may depend on how you look at it. – pguardiario
14 upvote
  flag
@pguardiario: I think it's really just a question of definitions. You're using a definition of "pass-by-reference" that you've personally come up with, while Jörg is using the traditional computer science definition. Of course, it is none of my business to tell you how to use words — I just think it's important to explain what the term normally means. In traditional terminology, Ruby is pass-by-value, but the values themselves are references. I totally understand why you and the OP like to think of this as pass-by-reference — it's just not the traditional meaning of the term. – Chuck
1 upvote
  flag
@Chuck, I agree that it's a question of definitions but I didn't make them up. Pass by value means a copy is sent to the method and it's clear that this isn't what is happening. – pguardiario
upvote
  flag
@pguardiario - it sounds like a copy IS sent to the method: a copy of the reference. – Riley Lark
1 upvote
  flag
In C++, "pass by value" means the function gets a copy of the variable and any changes to the copy don't change the original. That's true for objects too. If you pass an object variable by value then the whole object (including all of its members) get copied and any changes to the members don't change those members on the original object. (It's different if you pass a pointer by value but Ruby doesn't have pointers anyway, AFAIK.) – David Winiecki
1 upvote
  flag
In C++, "pass by reference" means the function gets access to the original variable. It can assign a whole new literal integer and the original variable will then have that value too. – David Winiecki
2 upvote
  flag
Ruby, Python, Java, JavaScript, and C#, use pass by value (in the C++ sense) if the argument is not an object. If the argument is an object, then "pass by object reference" (to use Python's terminology) is used: any of the object's members can have new values assigned to them and the original object will remember these changes, but assigning a whole new object to the variable causes the variable to stop referencing the original. Therefore it is not "pass by reference" in the C++ sense. – David Winiecki
4 upvote
  flag
Everything in Ruby is an object, so Ruby is neither pass by value nor pass by reference, at least in the sense those terms are used in C++. "pass by object reference" might be a better way to describe what Ruby does. In the end though, the best bet might be not to put too much meaning on any of these terms, and just get a good understanding of the behavior that really happens. – David Winiecki
upvote
  flag
@DavidWiniecki comment: if the argument is an object, then "pass by object reference". . Not C# which does what @Chuck comment says. C# default is pass by value - the reference variable is copied. That variable is an object's address, not the object. Unless explicitly using the ref keyword: RefMeBaby( ref addressOfBob );. Using ref is extremely rare. – radarbob

Is Ruby pass by reference or by value?

Ruby is pass-by-value. Always. No exceptions. No ifs. No buts.

Here is a simple program which demonstrates that fact:

def foo(bar)
  bar = 'reference'
end

baz = 'value'

foo(baz)

puts "Ruby is pass-by-#{baz}"
# Ruby is pass-by-value
13 upvote
  flag
@DavidJ.: "The mistake here is that the local parameter is reassigned (pointed to a new place in memory)" – That's not a mistake, that's the definition of pass-by-value. If Ruby were pass-by-reference, then reassignment to the local method argument binding in the callee would also have reassigned the local variable binding in the caller. Which it didn't. Ergo, Ruby is pass-by-value. The fact that if you change a mutable value, the value changes is completely irrelevant, that's just how mutable state works. Ruby is not a pure functional language. – Jörg W Mittag
4 upvote
  flag
Thanks to Jörg to defend the true definition of "pass-by-value". It's clearly melting our brain when the value is in fact a reference, though ruby always pass by-value. – Douglas
6 upvote
  flag
This is sophistry. The practical distinction between "pass by value" and "pass by reference" is a semantic, not a syntactic one. Would you say that C arrays are pass-by-value? Of course not, even though when you pass the name of an array to a function you are passing an immutable pointer, and only the data to which the pointer refers can be mutated. Clearly value types in Ruby are passed by value, and reference types are passed by reference. – dodgethesteamroller
2 upvote
  flag
@dodgethesteamroller: Both Ruby and C are pass-by-value. Always. No exceptions, not ifs no buts. The distinction between pass-by-value and pass-by-reference is whether you pass the value the reference points to or pass the reference. C always passes the value, never the reference. The value may or may not be a pointer, but what the value is is irrelevant to whether it is being passed in the first place. Ruby also always passes the value, never the reference. That value is always a pointer, but again, that is irrelevant. – Jörg W Mittag
upvote
  flag
In reality, some Ruby implementations actually do not always pass a pointer by value. They sometimes pass the value directly by value. However, they only do this for objects which have certain immutability guarantees from the Ruby Language Specification, so that this optimization doesn't change the observable behavior of the program (as all optimizations should). … – Jörg W Mittag
upvote
  flag
Since the difference between passing the object directly by value or passing a pointer to the object by value can only be observed when the object is mutated, and those specific objects (Fixnums, true, false, nil, Symbols, Floats) can't be mutated, it is safe for the compiler/interpreter to pass the object directly by value and not the pointer by value. But that is a performance optimization which doesn't change the observable behavior of the program – any Ruby program would behave exactly identical if pointers to Symbols and Fixnums were passed instead. – Jörg W Mittag
upvote
  flag
@JörgWMittag There is no such creature as a "Ruby Language Specification." We can only infer such a thing from Ruby's source code and/or its behavior. – dodgethesteamroller
upvote
  flag
@dodgethesteamroller: There are several creatures that one might reasonably call a "Ruby Language Specification". iso.org/iso/iso_catalogue/catalogue_tc/… is one. RubySpec.Org is another. The consensus of the implementors of the various Ruby Implementations is one, as is Matz's brain. And all of them agree: Ruby is pass-by-value. Period. – Jörg W Mittag
27 upvote
  flag
This answer, while strictly speaking true, is not very useful. The fact that the value being passed is always a pointer is not irrelevant. It is a source of confusion for people who are trying to learn, and your answer does absolutely nothing to help with that confusion. – user788472
1 upvote
  flag
If Ruby is pass-by-value because you always pass the value of a pointer, then a line like baz = 'reference' doesn't make much sense. A pointer is not a String. If you were manipulating the value of the reference, you would only be able to assign it to an other pointer. In this case = is not the assignment of a pointer, it is saying instantiate a new String and store a pointer to the String in bar. Basically, the example above states that we are working with pointers and then uses a String operation to prove it. The String is passed into foo by reference. The pointers are not. – spinlock
upvote
  flag
call bar.gsub!(/value/, 'reference') within the method. You will see that the outer object is indeed subject to mutation. effectively the only thing passed by value is the reference to the object. – karmajunkie
2 upvote
  flag
@karmajunkie: Yes, and that makes Ruby pass-by-value. It doesn't matter what is passed, it matters how it is passed, and as you say yourself, the pointer is passed by value. Ergo, Ruby is pass-by-value. C is also always pass-by-value, regardless of whether you pass an int or an int*. Just because you are passing a pointer doesn't change the calling conventions. You can imagine Ruby being like C, except that all methods take and return an opaque object_t* pointer. That's still pass-by-value. – Jörg W Mittag
upvote
  flag
Am I completely missing something here, or in some circumstances, Ruby is pass-by-reference, like each do for example ahimmelstoss.github.io/blog/2014/06/11/… – teaforchris
upvote
  flag
@cp5w: no, that has exactly nothing to do with pass-by-value vs. pass-by-reference. That's just plain mutation. Ruby is not a purely functional language, if you tell an object to change itself, it changes. If you tell a string to append an ! to itself, it will have an ! appended. – Jörg W Mittag
upvote
  flag
@JörgWMittag ok this makes sense. This behaviour with each do is just a little alien to me as I have only recently moved to Ruby. So it looks like I have to clone an object if I don't want to affect the original (or in my case, where the original is "read only") in an each do iteration? – teaforchris
upvote
  flag
@cp5w: Yes, that's one of the problems with mutable state, and why so many programmers are adopting purely immutable objects with referentially transparent methods even in non-purely functional languages like Java, or Ruby. (If you read, for example, books like Effective Java and Java Concurrency in Practice, the entire content of those two books can be pretty much summarized as "use functional programming".) If you have mutable state, you need to define tight contracts about who is allowed to mutate what in which way when or if you can't trust those contracts, you have to copy everything. – Jörg W Mittag
1 upvote
  flag
This is an unhelpful example. If the content of the function in this answer were bar.replace 'reference' then the output would be Ruby is pass-by-reference – Toby 1 Kenobi
upvote
  flag
@Toby1Kenobi: Yes, there are of course many ways to get this to print the wrong thing by modifying it to print the wrong thing. However, what your example would show is not pass-by-reference but rather shared mutable state, which is not the question here. Nobody (and certainly not me) claims that Ruby is a pure functional language. Of course, it has shared mutable state, and when you mutate shared state that mutation is visible everywhere. If I cut my hair, my hair is gone, regardless if you reference me has "Jörg" like my colleagues or "son" like my father. – Jörg W Mittag
upvote
  flag
@JörgWMittag I thought your example was trying to show that the function makes a copy of the string parameter so that when you change the string in the function the original string is not changed. That is why I made the comment above. Now I understand more, I see that what you are showing is that the function makes a copy of the reference to the string so that when you reassign the reference the original reference is not reassigned. If you had made this clear in your answer this would have saved a lot of confusion, probably for other people too. – Toby 1 Kenobi
upvote
  flag
Could you please explain this printing Ruby is pass-by-reference: def foo(bar) bar[0..-1] = 'reference' end; baz = 'value'; foo(baz); puts "Ruby is pass-by-#{baz}" – Saleh Rastani
upvote
  flag
@SalehRastani: you are mutating the object, not changing the reference. Mutating objects is perfectly allowed in Ruby, Ruby is not a purely functional language like Haskell. This has nothing to do with pass-by-reference vs. pass-by-value, it's simple mutation. – Jörg W Mittag

The other answerers are all correct, but a friend asked me to explain this to him and what it really boils down to is how Ruby handles variables, so I thought I would share some simple pictures / explanations I wrote for him (apologies for the length and probably some oversimplification):


Q1: What happens when you assign a new variable str to a value of 'foo'?

str = 'foo'
str.object_id # => 2000

enter image description here

A: A label called str is created that points at the object 'foo', which for the state of this Ruby interpreter happens to be at memory location 2000.


Q2: What happens when you assign the existing variable str to a new object using =?

str = 'bar'.tap{|b| puts "bar: #{b.object_id}"} # bar: 2002
str.object_id # => 2002

enter image description here

A: The label str now points to a different object.


Q3: What happens when you assign a new variable = to str?

str2 = str
str2.object_id # => 2002

enter image description here

A: A new label called str2 is created that points at the same object as str.


Q4: What happens if the object referenced by str and str2 gets changed?

str2.replace 'baz'
str2 # => 'baz'
str  # => 'baz'
str.object_id # => 2002
str2.object_id # => 2002

enter image description here

A: Both labels still point at the same object, but that object itself has mutated (its contents have changed to be something else).


How does this relate to the original question?

It's basically the same as what happens in Q3/Q4; the method gets its own private copy of the variable / label (str2) that gets passed in to it (str). It can't change which object the label str points to, but it can change the contents of the object that they both reference to contain else:

str = 'foo'

def mutate(str2)
  puts "str2: #{str2.object_id}"
  str2.replace 'bar'
  str2 = 'baz'
  puts "str2: #{str2.object_id}"
end

str.object_id # => 2004
mutate(str) # str2: 2004, str2: 2006
str # => "bar"
str.object_id # => 2004
5 upvote
  flag
Great reply, love the pictures! Definitely helped me grasp how ruby handles value/reference in a couple minutes. Granted, I knew when I wrote Ruby 4 yrs ago and completely forgot. :) – Jason
upvote
  flag
@Jason Glad you found it useful! – Abe Voelker
7 upvote
  flag
Wish I could favourite an answer! Very nice, respect. – Ian Vaughan
upvote
  flag
Great answer. I appreciate it! – xis
7 upvote
  flag
Answers like this always make me wonder why community-rank does not cause an answer to be ordered at-least below the accepted answer. – New Alexandria
upvote
  flag
One of the best answers i've seen in stackoverflow hands down – Sorcerer86pt
1 upvote
  flag
Robert Heaton also blogged about this lately: robertheaton.com/2014/07/22/… – Michael Renner

Parameters are a copy of the original reference. So, you can change values, but cannot change the original reference.

3 upvote
  flag
most concise correct answer – Toby 1 Kenobi

There are already some great answers, but I want to post the definition of a pair of authorities on the subject, but also hoping someone might explain what said authorities Matz (creator of Ruby) and David Flanagan meant in their excellent O'Reilly book, The Ruby Programming Language.

[from 3.8.1: Object References]

When you pass an object to a method in Ruby, it is an object reference that is passed to the method. It is not the object itself, and it is not a reference to the reference to the object. Another way to say this is that method arguments are passed by value rather than by reference, but that the values passed are object references.

Because object references are passed to methods, methods can use those references to modify the underlying object. These modifications are then visible when the method returns.

This all makes sense to me until that last paragraph, and especially that last sentence. This is at best misleading, and at worse confounding. How, in any way, could modifications to that passed-by-value reference change the underlying object?

1 upvote
  flag
Because the reference isn't getting modified; the underlying object is. – dodgethesteamroller
1 upvote
  flag
Because the object is mutable. Ruby is not a purely functional language. This is completely orthogonal to pass-by-reference vs. pass-by-value (except for the fact that in a purely functional language, pass-by-value and pass-by-reference always yield the same results, so the language could use either or both without you ever knowing). – Jörg W Mittag
upvote
  flag
A good example would be if instead of a variable assignment in a function, you look at the case of passing a hash to a function and doing a merge! on the passed hash. The original hash ends up modified. – elc

Is Ruby pass by reference or by value?

Ruby is pass-by-reference. Always. No exceptions. No ifs. No buts.

Here is a simple program which demonstrates that fact:

def foo(bar)
  bar.object_id
end

baz = 'value'

puts "#{baz.object_id} Ruby is pass-by-reference #{foo(baz)} because object_id's (memory addresses) are always the same ;)"

=> 2279146940 Ruby is pass-by-reference 2279146940 because object_id's (memory addresses) are always the same ;)

def bar(babar)
  babar.replace("reference")
end

bar(baz)

puts "some people don't realize it's reference because local assignment can take precedence, but it's clearly pass-by-#{baz}"

=> some people don't realize it's reference because local assignment can take precedence, but it's clearly pass-by-reference

upvote
  flag
This is the only correct answer and presents some nice gotchas: Try a = 'foobar' ; b = a ; b[5] = 'z', both a and b will get modified. – Martijn
2 upvote
  flag
@Martijn: your argument is not entirely valid. Let's go through your code statement by statement. a = 'foobar' creates a new reference pointing to 'foobar'. b = a creates a second reference to the same data as a. b[5] = 'z' changes the sixth character of the value referenced by b to a 'z' (the value which is coincidentally also referenced by a gets changed). That's why "both get modified" in your terms, or more precisely, why "the value referenced by both variables gets modified". – Lukas_Skywalker
2 upvote
  flag
You are not doing anything with the reference in your bar method. You are simply modifying the object that the reference points to, but not the reference itself. They only way to modify references in Ruby is by assignment. You cannot modify references by calling methods in Ruby because methods can only be called on objects and references are not objects in Ruby. Your code sample demonstrates that Ruby has shared mutable state (which is not under discussion here), it does however nothing to illuminate the distinction between pass-by-value and pass-by-reference. – Jörg W Mittag
upvote
  flag
When someone asks whether a language is "pass-by-reference" they usually want to know when you pass something to a function and the function modifies it, will it be modified outside the function. For Ruby the answer is 'yes'. This answer is helpful in demonstrating that, @JörgWMittag's answer is extremely unhelpful. – Toby 1 Kenobi
upvote
  flag
@Toby1Kenobi: You are of course free to use your own personal definition of the term "pass-by-value" which is different from the common, widely-used definition. However, if you do so, you should be prepared for people to be confused, especially if you neglect to disclose the fact that you are talking about a very different, in some aspects even opposite notion than everybody else does. In particular, "pass-by-reference" is not concerned with whether or not the "something" that is passed can be modified, but rather with what that "something" is, in particular, whether it is the reference … – Jörg W Mittag
upvote
  flag
itself that is being passed (pass-by-reference) or whether the value that the reference points to is being passed. In Ruby, it's the latter. Ergo, Ruby is pass-by-value. Now, it just so happens that the value is a pointer to a shared mutable object, and that when you mutate this object, other pieces of code that also have a pointer to this object can observe these modifications, but that has nothing to do with pass-by-reference vs. pass-by-value. That's just how shared mutable state works. Ruby is not a pure functional language, and nobody ever claimed that is was. – Jörg W Mittag
upvote
  flag
@JörgWMittag, sorry I spoke from ignorance. David Winiecki's answer has given me more understanding. I never knew that in C++ pass-by-reference when you reassigned a new value to the reference in the function the original reference would also be reassigned. I suppose this is the key difference between references and pointers in C++ that I never understood before. I thought Ruby's behavior was the same as pass-by-reference in C++, but it's not. – Toby 1 Kenobi
upvote
  flag
I like this answer because, in combination with JörgWMittag's answer, it shows how silly it is to use pass-by-value and pass-by-reference in the C++ sense of the terms when talking about Ruby. Both this example and Jörg's are perfectly valid examples that demonstrate Ruby exhibiting traits from both passing styles, so practically speaking neither definition really fits. – Ajedi32

Ruby is interpreted. Variables are references to data, but not the data itself. This facilitates using the same variable for data of different types.

Assignment of lhs = rhs then copies the reference on the rhs, not the data. This differs in other languages, such as C, where assignment does a data copy to lhs from rhs.

So for the function call, the variable passed, say x, is indeed copied into a local variable in the function, but x is a reference. There will then be two copies of the reference, both referencing the same data. One will be in the caller, one in the function.

Assignment in the function would then copy a new reference to the function's version of x. After this the caller's version of x remains unchanged. It is still a reference to the original data.

In contrast, using the .replace method on x will cause ruby to do a data copy. If replace is used before any new assignments then indeed the caller will see the data change in its version also.

Similarly, as long as the original reference is in tact for the passed in variable, the instance variables will be the same that the caller sees. Within the framework of an object, the instance variables always have the most up to date reference values, whether those are provided by the caller or set in the function the class was passed in to.

The 'call by value' or 'call by reference' is muddled here because of confusion over '=' In compiled languages '=' is a data copy. Here in this interpreted language '=' is a reference copy. In the example you have the reference passed in followed by a reference copy though '=' that clobbers the original passed in reference, and then people talking about it as though '=' were a data copy.

To be consistent with definitions we must keep with '.replace' as it is a data copy. From the perspective of '.replace' we see that this is indeed pass by reference. Furthermore, if we walk through in the debugger, we see references being passed in, as variables are references.

However if we must keep '=' as a frame of reference, then indeed we do get to see the passed in data up until an assignment, and then we don't get to see it anymore after assignment while the caller's data remains unchanged. At a behavioral level this is pass by value as long as we don't consider the passed in value to be composite - as we won't be able to keep part of it while changing the other part in a single assignment (as that assignment changes the reference and the original goes out of scope). There will also be a wart, in that instance variables in objects will be references, as are all variables. Hence we will be forced to talk about passing 'references by value' and have to use related locutions.

Try this:--

1.object_id
#=> 3

2.object_id
#=> 5

a = 1
#=> 1
a.object_id
#=> 3

b = 2
#=> 2
b.object_id
#=> 5

identifier a contains object_id 3 for value object 1 and identifier b contains object_id 5 for value object 2.

Now do this:--

a.object_id = 5
#=> error

a = b
#value(object_id) at b copies itself as value(object_id) at a. value object 2 has object_id 5
#=> 2

a.object_id 
#=> 5

Now, a and b both contain same object_id 5 which refers to value object 2. So, Ruby variable contains object_ids to refer to value objects.

Doing following also gives error:--

c
#=> error

but doing this won't give error:--

5.object_id
#=> 11

c = 5
#=> value object 5 provides return type for variable c and saves 5.object_id i.e. 11 at c
#=> 5
c.object_id
#=> 11 

a = c.object_id
#=> object_id of c as a value object changes value at a
#=> 11
11.object_id
#=> 23
a.object_id == 11.object_id
#=> true

a
#=> Value at a
#=> 11

Here identifier a returns value object 11 whose object id is 23 i.e. object_id 23 is at identifier a, Now we see an example by using method.

def foo(arg)
  p arg
  p arg.object_id
end
#=> nil
11.object_id
#=> 23
x = 11
#=> 11
x.object_id
#=> 23
foo(x)
#=> 11
#=> 23

arg in foo is assigned with return value of x. It clearly shows that argument is passed by value 11, and value 11 being itself an object has unique object id 23.

Now see this also:--

def foo(arg)
  p arg
  p arg.object_id
  arg = 12
  p arg
  p arg.object_id
end

#=> nil
11.object_id
#=> 23
x = 11
#=> 11
x.object_id
#=> 23
foo(x)
#=> 11
#=> 23
#=> 12
#=> 25
x
#=> 11
x.object_id
#=> 23

Here, identifier arg first contains object_id 23 to refer 11 and after internal assignment with value object 12, it contains object_id 25. But it does not change value referenced by identifier x used in calling method.

Hence, Ruby is pass by value and Ruby variables do not contain values but do contain reference to value object.

It should be noted that you do not have to even use the "replace" method to change the value original value. If you assign one of the hash values for a hash, you are changing the original value.

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

hash = {"test"=>"value"}
my_foo(hash)
puts "Ruby is pass-by-#{hash["test"]}"
upvote
  flag
Another thing I found. If you are passing a numeric type, all numeric type are immutable, and thus ARE pass by value. The replace function that worked with the string above, does NOT work for any of the numeric types. – Don Carr

Ruby uses "pass by object reference"

(Using Python's terminology.)

To say Ruby uses "pass by value" or "pass by reference" isn't really descriptive enough to be helpful. I think as most people know it these days, that terminology ("value" vs "reference") comes from C++.

In C++, "pass by value" means the function gets a copy of the variable and any changes to the copy don't change the original. That's true for objects too. If you pass an object variable by value then the whole object (including all of its members) get copied and any changes to the members don't change those members on the original object. (It's different if you pass a pointer by value but Ruby doesn't have pointers anyway, AFAIK.)

class A {
  public:
    int x;
};

void inc(A arg) {
  arg.x++;
  printf("in inc: %d\n", arg.x); // => 6
}

void inc(A* arg) {
  arg->x++;
  printf("in inc: %d\n", arg->x); // => 1
}

int main() {
  A a;
  a.x = 5;
  inc(a);
  printf("in main: %d\n", a.x); // => 5

  A* b = new A;
  b->x = 0;
  inc(b);
  printf("in main: %d\n", b->x); // => 1

  return 0;
}

Output:

in inc: 6
in main: 5
in inc: 1
in main: 1

In C++, "pass by reference" means the function gets access to the original variable. It can assign a whole new literal integer and the original variable will then have that value too.

void replace(A &arg) {
  A newA;
  newA.x = 10;
  arg = newA;
  printf("in replace: %d\n", arg.x);
}

int main() {
  A a;
  a.x = 5;
  replace(a);
  printf("in main: %d\n", a.x);

  return 0;
}

Output:

in replace: 10
in main: 10

Ruby uses pass by value (in the C++ sense) if the argument is not an object. But in Ruby everything is an object, so there really is no pass by value in the C++ sense in Ruby.

In Ruby, "pass by object reference" (to use Python's terminology) is used:

  • Inside the function, any of the object's members can have new values assigned to them and these changes will persist after the function returns.*
  • Inside the function, assigning a whole new object to the variable causes the variable to stop referencing the old object. But after the function returns, the original variable will still reference the old object.

Therefore Ruby does not use "pass by reference" in the C++ sense. If it did, then assigning a new object to a variable inside a function would cause the old object to be forgotten after the function returned.

class A
  attr_accessor :x
end

def inc(arg)
  arg.x += 1
  puts arg.x
end

def replace(arg)
  arg = A.new
  arg.x = 3
  puts arg.x
end

a = A.new
a.x = 1
puts a.x  # 1

inc a     # 2
puts a.x  # 2

replace a # 3
puts a.x  # 2

puts ''

def inc_var(arg)
  arg += 1
  puts arg
end

b = 1     # Even integers are objects in Ruby
puts b    # 1
inc_var b # 2
puts b    # 1

Output:

1
2
2
3
2

1
2
1

* This is why, in Ruby, if you want to modify an object inside a function but forget those changes when the function returns, then you must explicitly make a copy of the object before making your temporary changes to the copy.

upvote
  flag
Your answer is the best. I also wanna post a simple example def ch(str) str.reverse! end; str="abc"; ch(str); puts str #=> "cba" – fangxing
upvote
  flag
This is the correct answer! This is also very well explained here: robertheaton.com/2014/07/22/…. But what I still don't understand is this: def foo(bar) bar = 'reference' end; baz = 'value'; foo(baz); puts "Ruby is pass-by-#{baz}". This prints "Ruby is pass-by-value". But the variable inside foo is reassigned. If bar would be an array the reassignment would not effect baz. Why? – haffla
upvote
  flag
I don't understand your question. I think you should ask a whole new question instead of asking in comments here. – David Winiecki

Ruby is pass-by-value in a strict sense, BUT the values are references.

This could be called "pass-reference-by-value". This article has the best explanation I have read: http://robertheaton.com/2014/07/22/is-ruby-pass-by-reference-or-pass-by-value/

Pass-reference-by-value could briefly be explained as follows:

A function receives a reference to (and will access) the same object in memory as used by the caller. However, it does not receive the box that the caller is storing this object in; as in pass-value-by-value, the function provides its own box and creates a new variable for itself.

The resulting behavior is actually a combination of the classical definitions of pass-by-reference and pass-by-value.

upvote
  flag
"pass reference by value" is the same phrase I use to describe Ruby's argument passing. I think it's the most accurate and succinct phrase. – Wayne Conrad
Two references refer to same object as long as there is no reassignment. 

Any updates in the same object won't make the references to new memory since it still is in same memory. Here are few examples :

    a = "first string"
    b = a



    b.upcase! 
    => FIRST STRING
    a
    => FIRST STRING

    b = "second string"


a
    => FIRST STRING
    hash = {first_sub_hash: {first_key: "first_value"}}
first_sub_hash = hash[:first_sub_hash]
first_sub_hash[:second_key] = "second_value"

    hash
    => {first_sub_hash: {first_key: "first_value", second_key: "second_value"}}

    def change(first_sub_hash)
    first_sub_hash[:third_key] = "third_value"
    end

    change(first_sub_hash)

    hash
    =>  {first_sub_hash: {first_key: "first_value", second_key: "second_value", third_key: "third_value"}}

Not the answer you're looking for? Browse other questions tagged or ask your own question.