Есть ли ||оператор оценивает второй аргумент, даже если первый аргумент верен? - PullRequest
10 голосов
/ 06 февраля 2012

Я пытаюсь вычислить выражение (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, только если второй аргумент ||оператор оценивается, который никогда не должен основываться на документации?

Ответы [ 4 ]

11 голосов
/ 06 февраля 2012

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

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

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

4 голосов
/ 06 февраля 2012

Как сказал @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 голосов
/ 06 февраля 2012

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

2 голосов
/ 06 февраля 2012

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

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

...