a
Здесь вы оцениваете a
, который не определен. Следовательно, вы получаете исключение.
a || 1
Здесь вы все еще должны оценить a
, чтобы определить значение логического выражения. Как и выше, a
не определено. Следовательно, вы получаете исключение.
a = a || 1
Здесь a
определяется . Он определен как неинициализированная локальная переменная. В Ruby неинициализированные переменные оцениваются как nil
, поэтому правая часть выражения присваивания оценивается как nil || 1
, что соответствует 1
, поэтому возвращаемое значение выражения присваивания равно 1
, и побочный эффект состоит в том, что a
инициализируется как 1
.
РЕДАКТИРОВАТЬ: Кажется, что есть некоторая путаница, когда переменные определяются и когда они инициализируются в Ruby. Получение определяется в время разбора , но инициализируется в время выполнения . Вы можете увидеть это здесь:
foo # => NameError: undefined local variable or method `foo' for main:Object
foo
не определено.
if false
foo = 'This will never get executed'
end
На этом этапе определяется foo
, даже если строка никогда не будет выполнена. Тот факт, что строка никогда не выполняется, совершенно не имеет значения, потому что интерпретатор в любом случае не имеет к этому никакого отношения: локальные переменные определяются синтаксическим анализатором, и синтаксический анализатор, очевидно, видит эту строку.
foo # => nil
Нет ошибки, потому что определено foo
, и оно оценивается как nil
, потому что оно не инициализировано.