Почему 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)