Имеет ли || оператор оценивает второй аргумент, даже если первый аргумент верен?

Я пытаюсь оценить выражение (a=10) || (rr=20), в то время как переменная rr не определена

набрав rr в консоли ruby, прежде чем оценивать предыдущее выражение, верните

rr
NameError: undefined local variable or method `rr' for main:Object
from (irb):1
from :0

Когда я пишу выражение (a=10) || (rr=20), он возвращает 10, а когда я пишу rr после этого, он говорит nil

(a=10) || (rr=20)
rr  # => nil

Итак, почему это происходит? Не следует определять rr только в том случае, если второй аргумент || вычисляется оператор, который никогда не должен основываться на документации?

Ответ 1

Это происходит потому, что интерпретатор ruby ​​определяет переменную, когда видит ее присвоение (но до того, как она выполнит фактическую строку кода). Вы можете прочитать об этом в этом ответе.

Булево выражение OR (||) будет оценивать значение выражения левой руки, если оно не nil, а не false, else || будет оценивать значение выражения правой руки.

В вашем примере интерпретатор ruby ​​видит назначение a и rr (но еще не выполняет эту строку) и инициализирует (определяет, создает) a и rr с помощью nil, Затем он выполняет выражение ||. В этом выражении || a присваивается 10 и возвращается 10. r=20 не оценивается, а rr не изменяется (он все еще nil). Вот почему в следующей строке rr есть nil.

Ответ 2

Как указано в @DOC, && и || известны как условные операторы short circuited.

In case of ||, if the left part of || expression returns true, the right part won't be executed. Это означает, что правая часть будет выполнена только в том случае, если левая часть выражения || возвращает false.

In case of &&, right part of the && expression will be executed only if left part of && returns true.

В данном сценарии (a=10) || (rr=20), rr = 20 не будет выполняться, так как выражение ruby ​​a=10 возвращает true. Обратите внимание, что в выражении присваивания ruby ​​возвращает true, кроме nil and false.

Ответ 3

Я думаю, что определение переменных происходит на этапе синтаксического анализа, а не в момент выполнения. Поэтому, когда он оценивает линию, он анализирует все это, и переменная определена, но не назначена.

Ответ 4

Когда парсер обнаруживает переменную, он автоматически действует в контексте, в котором он определен. Оценка rr сама по себе недействительна. Оценка rr=20 достаточна, чтобы вызвать определение, даже если присвоение значения никогда не происходит.

Это причуда того, как Ruby пытается различать переменные и вызовы методов. Он несовершенен, но обычно работает наилучшим образом.