В Ruby существует двусмысленность между ссылкой на локальную переменную и отправкой сообщения в неявный получатель без списка аргументов. Это означает, что
foo
может означать либо «разыменования локальной переменной» или «отправить сообщение foo
к self
без аргументов», то есть он может быть либо эквивалентно
binding.local_variable_get(:foo)
или
self.foo()
# or
public_send(:foo)
Эта двусмысленность разрешена на Время разбора. Когда парсер встречает присвоение foo
, он будет с этого момента обрабатывать foo
в качестве локальной переменной независимо от того, действительно ли выполняется назначение. (Это то, что синтаксический анализатор не может определить статический, в конце концов. Вдумайтесь if rand > 0.5 then foo = 42 end
.)
В скомпилированном языке это даже не компилируется.
Нет такой вещи, как скомпилированный язык. Компиляция и интерпретация являются признаками компилятора или интерпретатора (duh!), А не языка. Языки не компилируются и не интерпретируются. Они всего лишь являются.
Каждый язык может быть реализован с помощью компилятора, и каждый язык может быть реализован с помощью интерпретатора. Большинство языков имеют как скомпилированные, так и интерпретированные реализации (например, C имеет GCC и Clang, которые являются компиляторами, а Cint и Cling - интерпретаторами, Haskell имеет GHC, который является компилятором, и Hugs, который является интерпретатором).
Многие современные языковые реализации имеют как в одной реализации, так и в разных фазах (например, YARV и MRuby компилируют исходный код Ruby на внутренний байт-код, а затем интерпретируют этот байт-код) или в смешанном режиме (например, HotSpot JVM оба интерпретируют и компилируют байт-код JVM, в зависимости от того, что имеет больше смысла) или оба (например, Rubinius компилирует исходный код Ruby в байт-код Rubinius на первом этапе, а затем компилирует этот байт-код на собственный код и интерпретирует его, в зависимости от того, что имеет больше смысла).
В самом деле, все существующие в настоящее время реализация на Ruby компилируются: YARV и MRuby компилировать свои собственные внутренние форматы байткодом, Rubinius, MacRuby, MagLev и Топаз компилировать свои собственные внутренние форматы байткодом, затем компилировать что к родным кода, JRuby компилируется в байт-код JVM (который JVM может или не может компилировать дополнительно), IronRuby компилируется в байт-код CIL (который VES может или не может компилировать далее).
Тот факт, что Ruby ведет себя таким образом, заключается в том, что спецификация языка так говорит. Не потому, что Ruby «интерпретируется», потому что на самом деле это не так. Единственной чисто интерпретируемой реализацией Ruby была МРТ и очень ранние версии JRuby, и они давно уже ушли на пенсию.
Это потому, что Ruby устанавливает локальные области переменных во время разбора. 'a' используется как локальная переменная в этой области, поэтому Ruby рассматривает ее как локальную переменную (хотя она никогда не инициализируется). –
@MarekLipka интересно. Я понял, что это может быть синтаксический анализ, поэтому я использовал тег AST для этого вопроса. – jlhonora
Прочтите его из http://ruby-doc.org/core-2.1.2/doc/syntax/assignment_rdoc.html#label-Local+ Переменные + и + Методы –