3223 views
What is the return value of the following Ruby code?
class Person def firstname = "Jon" def lastname = "Jones" def fullname lastname = "Snow" if false "#{firstname} #{lastname}" end end Person.new.fullname # => ???
The correct answer is
It raises NameError
"Jon Jones"
"Jon Snow"
"Jon "
Subscribe to RubyCademy and get free access to all our courses, plus hundreds of fun Ruby cards, quizzes, guides, and tutorials!
At first, Person#lastname
is called.
Then a lastname
local variable is created with a default value of nil
as lastname = "Snow"
is never executed due to the if false
clause.
Finally, the final call to lastname
("#{firstname} #{lastname}"
) returns nil
as it is the freshly created local variable that is called.
So Person#fullname
returns "Jon "
as Person#firstname
returns Jon
and the lastname
local variable is equal to nil
.
Let's slightly modify our code example to see what happens behind the scenes
class Person def lastname = "Jones" def fullname lastname lastname = "Snow" if false lastname end end puts RubyVM::InstructionSequence.disasm(Person.new.method(:fullname))
OUTPUT
0000 putself ( 5)[LiCa] 0001 opt_send_without_block <calldata!mid:lastname, argc:0, FCALL|VCALL|ARGS_SIMPLE> 0003 pop 0004 getlocal_WC_0 lastname@0 ( 7)[Li] 0006 leave ( 8)[Re]
Firstly, we can see that a method with the mid
(method identifier) lastname
is called.
opt_send_without_block <calldata!mid:lastname, argc:0, ...>
Then the lastname
local variable is called
getlocal_WC_0 lastname@0
So once a local variable is referenced in the same scope, the local variable is created with the default value nil
even if the referenced local variable is within a clause that is not executed like the if false
one.
Voilà!
Subscribe to RubyCademy and get free access to all our courses, plus hundreds of fun Ruby cards, quizzes, guides, and tutorials!
RubyCademy ©