Object Passing & Mutability in Ruby
Variable Assignment and Variable References in Ruby:
In ruby our assignment operator
= allows us to point variables at objects.
Let us jump into some code and explore this further.
Below we will assign two variables to a single string object and see how this works.
acknowledgement = "Hello"acknowledgement.object_id #=> 100------------------------------------------salutations = acknowledgementsalutations.object_id #=> 100
Here we have two different variables pointing at (also called referencing) one single object.
First we assign
acknowledgement to the String object
Then we assign
salutations to point at the String object that
acknowledgement points to.
Variable Reassignment, Mutation, and Non Mutating Methods in Ruby:
acknowledgement = "Goodbye"
acknowledgement.object_id #=> 120 salutations #=> "Hello"
salutations.object_id #=> 100
In the above code we have reassigned
acknowledgement to reference a new String object
Objects in Ruby can either be mutable or immutable.
Immutable means it cannot be modified. Conversely,
mutable means the object can be modified.
For example, numbers and booleans are immutable, while strings are mutable in Ruby. There are no methods available within Ruby that allow you to mutate an immutable object.
1.) int = 102.) p int #=> 10 3.) int = 10 * int4.) p int #=> 100
Wait, doesn’t line 4 show that we just mutated an immutable object?
Most definitely not.
- Here we assign variable
inta value of
- We pass
10(the object referenced by local variable
pas an argument, this shows us that the assignment from line 1 has been carried out successfully.
- Here we reassign
intto the return value of
10 * int.
- We pass the object that
intpoints to as argument to
p, which outputs
100, this shows us that the reassignment from line 3 has been carried out successfully.
In the above example we have reassigned the variable to point at a different object. We have not mutated the original object.
Assignment simply tells Ruby to bind an object to a variable. It does not mutate the object. When using
= (assignment) remember you are not mutating your object, you are pointing at new objects.
Add AND Assignment Operator
This is not a method, this is an assignment operator.
It adds the right operands and left operands and assigns the result to the left.
Take a look at the example below:
a = 10
b = 12a += bp a #=> 22
p b #=> 12
In the above example
a += b is the same as saying…
a = a + b
We are adding the current value of the left side to the right side and saving the result to the left side.
Let’s dig deeper:
What do you think happens with the below code snippet?
str += '!!'
annoyed = "go away"
angry = non_mutation(annoyed)
annoyed is passed to our method
non_mutation . This points the method parameter
str to our string object
annoyed now point to the same String object
On the second line, we have reassigned
str which now points at the String object
“go away!!” , a completely new object.
At this point
annoyed is still pointing at String object
“go away" . While
str is pointing at the new object
String #upcase returns a copy of str with all lowercase letters replaced with their uppercase counterparts.
One the third line, we call the string method
#upcase on the object our variable
annoyed is still pointing at the original string object
“go away” .
#upcase is called on
str which returns
“GO AWAY!!” .
As we have seen, the original String object passed in to
non_mutation remains un-mutated.
On the last line, our variable
angry is therefore assigned to the return value of invoking
non_mutation with the string object that
annoyed references, passed as an argument.
The above code snippet is non-mutative.
str << '!!'
asking = "come here"
mutation(asking) #=> "COME HERE!!"
On the last line, we invoke
mutation and pass the string object
“come here” that our variable
asking references. At this point, now
asking both reference this object.
The Shovel Operator
Appends the given object to str. (This is a mutating method, which modifies the original object it is called on.)
On line 2, the shovel operator
<< mutates the object that both
asking point at, which now is
“come here!!” .
Upcases the contents of str, returning
nilif no changes were made.
On line 3, we call String method
#upcase! on the string object that
#upcase! is mutative and modifies the object in place, this is returned as it is the last line of the method (again implicit return value).
At this point both
mutation method’s parameter) and the local variable
asking are pointing at the same object, that is
“COME HERE!!” .
This object has been mutated in place by invoking our method
mutation and passing the local variable
asking as an argument.
As you can see, this code snippet is mutative.