Ruby Object Mutability
How does Ruby work to reference objects?
This article is written to clarify how Ruby works in order to help you be aware of what’s going on in the background. Forewarned is forearmed, after all.
When we create a, the string itself is not stored. If you include:
print ‘Hello World' in your code, the string
‘Hello World’ is not stored for later use. It is used and forgotten.
However, often we want to reuse code and change it. This is where variables are introduced.
Variables allow us to save some information and recall it later.
my_variable = ‘Hello World’
The simplest practical use for this can be illustrated with a greeting where the program stores the user’s name and says hello to them like so:
puts ‘What is your name?’
name = ‘nathan’
puts ‘Hello ‘ + name
But how does this work? What is going on in the background that allows Ruby to store the user’s name and then subsequently refer to it later?
When the variable,
name is created, Ruby assigns an object identification number to it. Personally, I find that the simplest way to conceptualise this is by thinking about it in terms of documents.
The Ruby code lives in it’s own little file somewhere. I mean, not really — uhhh maybe… but it definitely does for this example, okay?
When the program runs, it opens the document and like a human, fulfills it’s tasks one by one going down the page like a to-do list. Except, not like a human at all..
When it gets to the part of
name = nathan, it creates a file called
name with a value of ‘nathan’ within a new folder, like so.
If we want to check what the value of name.txt is, we would have to open the file though referencing the associated file path.
Which would be something like
This folder path is similar to the object id Ruby creates for a variable.
Simple so far, right?
Copying the Variable
What happens when you copy the variable and assign it a new name?
new_name = name
Well, this happens.
What’s going on here? They have the same id. Ruby isn’t even copying a file, it’s creating an alias for the same file.
Basically, it gets a nickname. Now, if you call it by it’s original name or the new name, it’ll respond.
Usefulness: Because both names are referring to the same object, what one does to it will do to the other. Because it’s the same thing.
Similarly, if Mr John Doe, nicknamed ‘Johnny boy’ decides to get a haircut, both Mr John Doe and ‘Johnny boy’ get a haircut because they’re the same person.
This is best seen like so:
What effects one effects the other.
Reassigning the Variable
However, when we directly change the variable, like so only one of them changes.
The difference this time is that we are essentially cloning ‘Mr John Doe’ from before and changing the clone that’s given the name ‘Johnny boy’. Mr John Doe remains the same but is no longer the same as Johnny boy. Like so:
Going back to my file structure analogy, now there is two seperate folders each containing a ‘name.txt’ file. The contents of each can differ because they have a different file path and are not the same file.
Okay, so now we understand the process of how files change their uniqueness or object id. However, some objects can never change their contents. Their ‘name.txt’ file is locked or read-only.
Which objects change and which don’t vary according to the different programming languages. In Ruby, numbers and booleans don’t change; they are immutable. (note: this is by default, but you can make anything an immutable object if it can’t be changed)
But wait! How does a variable update? We do it all the time!
x = 1
x += 1
If you were to run this code, you would get 2 printed on the screen. Simple, right? In practice, yes. Behind the scenes, no.
What’s going on is actually a little complicated. When
x = 1 is created, a new object id is created, x with a value of 1. We think of this as a new folder that contains a file, called x.txt and inside x.txt the value 1 is stored.
The file path is C:\Users\User\Desktop\My Program\1547865\x.txt
When we go to execute the next line of code, x += 1, we go to update x.txt to store the value of 2. But wait! There’s a problem. x.txt is read-only which means that we can’t edit it.
To change the value of x.txt, we have to cheat a little.
Notice what I did?
I now have a file, x.txt with a value of 2. It’s file path, or unique id, is C:\Users\User\Desktop\My Program\2545247\x.txt
Ruby does the same thing.
Usefulness: It is important to note that just like in the file explorer, the old object id still exists. If it is not referenced or used elsewhere in the code, this essentially means that it is a useless file that is taking up space. Or the Ruby equivalent, anyway.
On the other hand, mutable objects are objects where the .txt file is *not* read-only and you can directly change it’s contents and rewrite it. Take the following example:
In this example, the list array is changed but the object id remains the same. Going back to the folder example, the reason for this can be illustrated. When we create the list array with 5 items, it looks like this:
Each item has it’s own .txt file where it stores the value of that item. When we modify the list, we create a new file path for the new file, keep the old file like before and then update the new value.txt file with the new value
So while it appears that no object ids changed, they did — it just wasn’t the
listobject id. If we look at what’s going on in ruby, we can see that the object.id of
list has changed even if the object id of
list remains the same.
This article has explained how objects are referenced. A variable is just a shorthand to target a object id. One object id can be referenced by multiple variables.
When one variable updates the object id, it is updated for all variables. We can assign one of the variables to a new id while leaving the other variable assigned to the original id.
We have gone over the difference between mutable and immutable objects. When an immutable object is updated, behind the scenes a new object is created that is associated with the variable and the old one stays in the background as a garbage file.