Ruby – Parameters by reference or by value? [duplicate]

This question confuses people because there is a thing called a reference type and there is a thing called pass-by-reference, but they don’t actually have all that much to do with each other.

References and values and values that are references: A (sorta) brief overview

In a pass-by-reference scenario, the parameters of a function are references to the variables that were passed into the function, and modifying the parameters modifies the original variables. This is not what Ruby is. For example, let’s look at the following code:

def inc(val)
  val += 1
end

a = 1
inc a
puts a

If Ruby were a pass-by-reference language, this program would print 2, because the val += 1 in inc would increment the value of a. But that isn’t what happens. The variable val is not a reference to the variable a — it’s an independent variable that is given the same value.

“But wait!” you say. “What if we were dealing with objects? Surely object variables are passed by reference, right?”

Nope.

def change_string(str)
  str << " I can insult you all you want"
  str << " because you'll never see this"
  str << " because I'm going to replace the whole string!"
  str << " Haha you smell bad!"
  str = "What? I didn't say anything." # I'm so sneaky
end

be_nice_to_me = "hello"
change_string(be_nice_to_me)
puts be_nice_to_me

If Ruby were pass-by-reference, you’d never see how mean the change_string method is, because the str = "What, I didn't say anything." would totally replace the value of be_nice_to_me with the string "What? I didn't say anything." But in fact change_string‘s sins are laid bare for all to see. How is this possible if Ruby doesn’t pass by reference?

Well, remember those reference types I talked about earlier? Well, that’s what objects are in Ruby. A reference type is a type whose value is a reference to something else. In this case, the variable’s value is a reference to the string "hello". When you pass the string, the variable’s value — which is a reference — is copied into the variable str. So now they both hold references to the same object, but str is not a reference to be_nice_to_me. So when you modify the object, those changes show up because they’re both referring to the same object. But when you modify one variable, the other doesn’t see it because neither variable is a reference to the other.

So is Ruby pass-by-reference or pass-by-value? It’s pass-by-value, but all the values are references.

Leave a Comment