Почему Ruby вызывает ошибку для последней неопределенной переменной в строке?

Предполагая, что foo, bar и baz не определены, строка

foo bar baz

вызывает эту ошибку:

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

В REPL для Python, PHP и Javascript первая проблема в foo(bar(baz)) заключается в том, что foo не определен. Почему Ruby сначала жалуется на baz?

Ответ 1

Ruby позволяет использовать первый метод (baz) для динамического определения двух других методов. Он не пытается разрешить foo или bar как вызовы метода до тех пор, пока не произойдет фактический вызов метода, и он никогда не достигает этого вызова метода, поскольку baz сначала вызывает ошибку.

Если baz динамически определяет методы foo и bar, нет проблем:

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

foo bar baz # => "foo bar baz!"

Ответ 2

Отправить эту статью ruby-magic-code-interpretation

& проверить его в консоли

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 

Поскольку рубиновый интерпретатор упорядочивает этот способ, он выдает ошибку

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