378 views
What is the return value of the following Ruby code?
def my_method(a) a += [4] end a = [1, 2, 3].freeze my_method(a) a # => ???
The correct answer is
[1, 2, 3, 4]
It raises FrozenError
[1, 2, 3]
Subscribe to RubyCademy and get free access to all our courses, plus hundreds of fun Ruby cards, quizzes, guides, and tutorials!
Array#+
does not modify self
. Indeed, it simply returns a new instance of Array
that is reassigned to a
.
a = [1].freeze a.object_id # => 17320 a = a + [2] # => [1, 2] a.object_id # => 30460
So the first frozen
array assigned to a
is replaced by the new Array
returned by Array#+
.
Firstly, let's define what is a variable in Ruby: a variable is a label that points to a specific object.
Now that we're more familiar with what a variable is in Ruby, let's see what happens when a variable value is passed as an argument of a method call.
In Ruby, when an object is passed as an argument of a method call, a private variable that points to the exact same object is created
var = Object.new var.object_id # => 7320 def my_method(arg) arg.object_id # => 7320 end my_method(var)
Here, var
points to an instance of Object
with the object ID 7320
.
We can also see that arg
points to the exact same object as var
during the call to my_method(var)
.
In this case, we say that arg
is a private copy of var
.
Now, what happens when we try to change the value of a private copy?
var = Object.new var.object_id # => 7320 def my_method(arg) arg.object_id # => 7320 arg = Object.new arg.object_id # => 20600 end my_method(var) var.object_id # => 7320
Here, var
and arg
point to the exact same instance of Object
with object ID 7320
.
Then a new instance of Object
is reassigned to arg
.
So, at this moment var
and arg
point to 2 different instances of Object
.
That's why, once the method call is terminated, var
still points to the same object as prior the method call.
Subscribe to RubyCademy and get free access to all our courses, plus hundreds of fun Ruby cards, quizzes, guides, and tutorials!
RubyCademy ©