Is Ruby pass-by-reference or pass-by-value?

Jun 26, 2018 - 3 min read
Is Ruby pass-by-reference or pass-by-value?
Share

As you learn your way through Ruby’s OOP, you will eventually stumble upon the concept of object passing. It might not be very clear if Ruby uses pass-by-reference or pass-by-value to send objects to a method. So I’m going to explain how all that works.

What is pass-by-reference?

Pass-by-reference means that the arguments of a method are references to the variables that were passed into the method, and modifying the arguments modifies the original variables.

val = "Hello"

def my_method(arg)
  arg = "Hi"
end

my_method(val)
puts val # => In pass-by-reference the result would be "Hi"

If Ruby were pass-by-reference, changing the value of the argument (arg) would change the value of the variable val. That is because in pass-by-reference, arg is a reference, a memory address. It’s not the actual string "Hello".

What is pass-by-value?

On the other hand, pass-by-value means that the arguments of a method are the values of the variables that were passed into the method, and modifying the arguments does not modify the original variables.

val = "Hello"

def my_method(arg)
  arg = "Hi"
end

my_method(val)
puts val # => In pass-by-value the result would be "Hello"

What is a reference type?

There’s one more concept you need to understand before I can answer the main question. And that is about reference types.

A reference type is a type whose value is a reference to something else. Let me explain.

Reference Type

So when you pass the variable some_string to a method, the method receives a copy of some_string‘s value, which is a reference.

Pass By Value

As you can see in the image, what is passed into my_method is not a reference to some_string. It’s the value of some_string. But that value is actually a reference to the Hey There! object.

That means that if you were to modify arg, the changes would be seen by some_string, because they are both refering the same object in memory.

Example:

some_string = "Hey There!"

def my_mehtod(arg)
  # Changing the value of `arg`
  arg = "Hello!"
end

my_mehtod(some_string)

puts "The value of some_string is: #{some_string}"
# => The value of some_string is: Hey There!

Now, let’s change the behavior of my_method to modify the object that it references.

some_string = "Hey There!"

def my_mehtod(arg)
  # Changing the value of the object it references
  arg.gsub!(/Hey/, "Hi")
end

my_mehtod(some_string)

puts "The value of some_string is: #{some_string}"
# => The value of some_string is: Hi There!

See what happened there? By changing the actual string that arg was refering to, made it visible to some_string because we changed the object that both arg and some_string refer to.

So is Ruby pass-by-reference or pass-by-value?

As you can see from the examples above, what is actually passed into the method is the value. But that value is actually a reference. So even though the terminology is confusing, I would say Ruby is pass-by-value, but all the values are references.

12 Project Ideas
Cezar Halmagean
Software development consultant with over a decade of experience in helping growing companies scale large Ruby on Rails applications. Has written about the process of building Ruby on Rails applications in RubyWeekly, SemaphoreCI, and Foundr.