Explain pass-by-reference and pass-by-value (in Ruby) like I am five

I'm having a hard time understanding the underlying technical difference between pass-by-reference and pass-by-value (in Ruby). I keep hearing that the distinction between pass by value and pass by reference is important. But I still can't wrap my head around it. Help? 😘

Did you find this post useful? Show some love!
DISCUSSION (8)

I think the value/reference stuff in Ruby is similar to Java: Variables are always references to objects (in Ruby everything is an object).

That means when you assign a variable to an object, you can imagine the variable as an arrow that points to the object. If you have a = b = _some_object_, that’s like having two arrows both pointing to the same object.

Re-assigning a variable, e.g. a = _some_other_object_, just points the arrow to another object. It doesn’t change the object it was pointing to before. On the other hand, dereferencing the variable, e.g. a.x = _something_, changes the underlying object. That means the change is visible to any variable pointing to the same object. If you don’t want this behavior, you have to explicitly make a copy of the object before you make a change to it.

Lastly, when you pass a variable to a function, a copy of the reference is made. That means there’s one arrow pointing to the object in the calling function and another arrow pointing to the same object in the called function. Since a copy is made, we say the argument is passed by value. But keep in mind that the argument is a reference (an arrow), so we are passing references by value.

One more note: You can create so-called “immutable” objects. That just means that methods that modify such objects will actually create a copy. The original object remains unchanged and instead a new object is created with the desired modification. As I mentioned earlier, creating copies like this can make it seem you’re dealing with values rather than references. Primitive objects like integers, e.g. 3, are immutable. That’s why doing 3 + 3 doesn’t change what 3 means, which of course would be bad!

See also: shallow vs. deep copy

Thanks for chiming in! This was really helpful Nested. 🙌

This is tricky to think about in Ruby because IMO the pass-by-value/reference distinction comes from languages where these are both possible as different behaviors, and Ruby is not really designed to be thought of in that way. Ruby is technically ALWAYS pass-by-value, but all variables and arguments are references to objects. Confused yet?

Pass by value: You give your friend a toy (pass your method an argument). It's theirs now, and you don't play with it anymore. Maybe you have an identical toy at home, but whatever your friend does to their toy doesn't affect yours.

Pass by reference: You tell your friend where your toy is. Now, whatever they do to the toy (pose it, cut its hair, whatever), you will find the toy as they left it next time you play with it.

How Ruby works: You give your friend a treasure map (a reference to an object). You can pass your friend a treasure map just like another one you have, and changes to their map don't affect yours. If they redraw their map, yours doesn't change.

def change(str)
  str = 'Nothing here!'
end

var = 'Treasure'
change(var) # => 'Nothing here!'
var         # => 'Treasure'

But if they follow the map to the treasure and mess with it...

def change(str)
  str << ' used to be here :('
end

var = 'Treasure'
change(var) # => "Treasure used to be here :("
var         # => "Treasure used to be here :("

More here.

I'm glad to read that I'm not the only one who has been confused by this! Thanks Brian 😃

In general pass-by-value is just creating a copy of a value and passing it to a function.
You can kinda "simulate" this behavior by using the Object#dup method.

h = {}

def fun(value)
  puts value.object_id
end

fun(h) # => 47450799554260
fun(h.dup) # => 47450799938380

Just keep in mind that dup is just a shallow copy.

Ben Halpern DEV.TO FOUNDER

Hey there, we see you aren't signed in. (Yes you, the reader. This is a fake comment.)

Please consider creating an account on dev.to. It literally takes a few seconds and we'd appreciate the support so much. ❤️

Plus, no fake comments when you're signed in. 🙃

Imagine you're a five, and you want a sandwich.

Mom has a sandwich right now.

"Mom, can I have a sandwich? "

There's 2 things Mom can do:

A) "Sure hon', I'll give you my sandwich."
B) "Alright, let me make you another sandwich."

You get a sandwich from Mom, take some bites out of it, and gives it back to Mom.

Here's the key difference between "Pass-by-reference" and "Pass-by-value" that is important to understand:
Is the object passed A) the original object, or B) a copy?

Pass-by-reference means you pass the original object. Any modifications you make to the object you receive is made on the original. Mom gets back her original sandwich that's half eaten.

Pass-by-value means you pass a copy of the object. Any modifications you make to the object you receive is made on the copy. Mom still has her original sandwich, but she also gets back the half eaten sandwich she made for you.

This difference is important to know, in any programming language - not just Ruby - because you could mistakenly pass an object by reference to a function that was not intended to be modified, or you could pass an object by value and wonder why wasn't the object updated by the function.

Hope that helps!

Say you are in preschool. In your school, there are a bunch of toys. Each toy has a specific place it's kept.

Now, let's say today you've decided you want to play with the bouncy ball. You play with the ball and when you're done you put it back where it belongs.

Then, your friend who is new to school asks if you can get her the basket ball, as she would like a turn but doesn't know where it's kept.

You decide to help your friend but you can do it in one of two ways. You can either go get the ball from it's place and hand it to your friend (pass by value) or you can show your friend where the ball is kept so she can get it her self (pass by reference).

The benefits of showing her where the ball is (pass by reference) is that you don't have to take the time and energy to actually get the ball for her. Also, if she decides she doesn't want to play with the ball, she doesn't need to spend the time or energy to get it but still has the knowledge of where the ball is, if she needs to help someone else find the ball.

In summary, sharing is caring.

Wow! This was really helpful Colin. Than you 😃

Classic DEV Post from Jun 26

Books vs Online Courses

Which the two learning methods is better for learning a new programming language?

READ POST
Follow @kostassar to see more of their posts in your feed.
laurosilvacom
I design, build, and maintain Ruby on Rails web apps. I aslo write technical publications on web development and remote work.
More from @laurosilvacom
Explain the difference between strings and symbols like I am five
#explainlikeimfive #ruby
Trending on dev.to
What is the difference between Methods, Computed, and Watchers?
#explainlikeimfive #vue #javascript
The Dangers of Drinking and Refactoring
#ruby #rails #wtf #drunk
Please keep using Ruby
#ruby #healthydebate
Explain JavaScript Promises like I am five.
#discuss #explainlikeimfive #javascript
Methods, blocks and sorting in Ruby
#ruby
How to Reduce Memory Usage for Rails and Sidekiq
#ruby #rails #sidekiq #webdev
Pieces of an App: The Files You Need to Start a Rails App
#ruby #beginners #webdev
Building My First Sinatra-based Ruby App: Thoughts and Wrap-up
#sinatra #ruby #beginners