Local variables

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 "

Unlock Your Ruby Potential

Subscribe to RubyCademy and get free access to all our courses, plus hundreds of fun Ruby cards, quizzes, guides, and tutorials!

Explanation

TL;DR

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.

Disasm

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à!

Unlock Your Ruby Potential

Subscribe to RubyCademy and get free access to all our courses, plus hundreds of fun Ruby cards, quizzes, guides, and tutorials!

RubyCademy ©