Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does Ruby raise error for last undefined variable on line?

Assuming that foo, bar, and baz have not been defined, the line

foo bar baz

raises this error:

NameError (undefined local variable or method `baz' for main:Object)

In REPLs for Python, PHP, and Javascript the first issue in foo(bar(baz)) is that foo is not defined. Why does Ruby complain about baz first?

like image 373
Sammy Taylor Avatar asked Jun 08 '18 19:06

Sammy Taylor


2 Answers

Ruby allows the first method invoked (baz) to dynamically define the other two methods. It doesn't attempt to resolve foo or bar as method invocations until the actual method invocation happens, and it never reaches that method invocation as baz first causes an error.

If baz dynamically defines the methods foo and bar, there is no problem:

def baz
  define_method(:foo) { |x| "foo #{x}" }
  define_method(:bar) { |x| "bar #{x}" }
  "baz!"
end

foo bar baz # => "foo bar baz!"
like image 113
meagar Avatar answered Oct 23 '22 08:10

meagar


Ref this post ruby-magic-code-interpretation

& check it in console

2.3.1 :001 > puts RubyVM::InstructionSequence.compile("foo bar baz").disasm
== disasm: #<ISeq:<compiled>@<compiled>>================================
0000 trace            1                                               (   1)
0002 putself          
0003 putself          
0004 putself          
0005 opt_send_without_block <callinfo!mid:baz, argc:0, FCALL|VCALL|ARGS_SIMPLE>, <callcache>
0008 opt_send_without_block <callinfo!mid:bar, argc:1, FCALL|ARGS_SIMPLE>, <callcache>
0011 opt_send_without_block <callinfo!mid:foo, argc:1, FCALL|ARGS_SIMPLE>, <callcache>
0014 leave            
 => nil 

As ruby interpreter order this way it throws the error

NameError (undefined local variable or method `baz' for main:Object)
like image 35
Salil Avatar answered Oct 23 '22 07:10

Salil