Почему истина && "строка" возвращает "строку"
Допустим, у меня есть что-то вроде
true && true #=> true
Что имеет смысл, поэтому я пытаюсь что-то вроде:
true && "dsfdsf" #=> "dsfdsf"
Что удивляет меня, потому что часто я буду делать что-то вроде if something && something
и я всегда думал, что это оценивает как истину и вернет истину. Дальнейшие эксперименты делают такие вещи, как:
jruby-1.7.3 :009 > "ad" && "dsf"
=> "dsf"
jruby-1.7.3 :010 > "ad" && "sdfd" && nil
=> nil
jruby-1.7.3 :011 > "ad" && nil && "sdf"
=> nil
создается впечатление, что Ruby возвращает либо последнее значение, если все верно, либо первое ложное значение, которое он находит. Почему это делает это? и это правильная ментальная модель?
2 ответа
Булевы операторы в ruby являются короткими замыканиями: если возможно определить значение выражения из левого аргумента, правый аргумент не оценивается.
Следовательно, более простая ментальная модель для оценки логического выражения, включающего &&
состоит в рассмотрении первых выражений, включающих только два операнда: левый операнд вычисляется первым; если значение этого операнда nil
или же false
операнд возвращается, а правый операнд не оценивается; если левый операнд - это что-то еще, правый оператор вычисляется и возвращается его значение.
Из этого определения ясно, что, как вы заметили, выражения с логическими операторами не возвращаются true
или же false
, но просто истинное значение или ложное значение. Стоит отметить, что это не имеет никакого значения в контексте, где логическое выражение используется только для его истинности или ложности.
Будучи булевыми операторами слева-ассоциативными, легко определить порядок вычисления выражения, содержащего более одного оператора, помня, что &&
имеет более высокий приоритет, чем ||
(будьте осторожны, однако, что and
а также or
имеют такой же приоритет). Сделав это, мы можем легко увидеть, что значение выражения является последним оцениваемым элементом, то есть элементом, который позволяет определить общую истинность или ложность выражения.
В ваших примерах (выражение состоит только из &&
операторы) значение выражения известно, как только встречается первое ложное значение или после того, как последний элемент был оценен как истинное значение; таким образом, последний оцененный элемент будет последним элементом, если все предшествующие ему элементы имеют истинное значение, и первым элементом с ложным значением, если таковые имеются.
Вы можете спросить, почему значение выражения не преобразуется в true
или же false
; на самом деле, этот тип поведения может быть использован в идиомах, таких как
x = x || default
или более краткий
x ||= default
это используется для проверки, если x
является nil
и, в этом случае, назначьте ему значение по умолчанию.
Да, он возвращает последнее оцененное значение. Вы можете преобразовать логическое значение, если хотите:
2.0.0p247 :016 > a = "s"
=> "s"
2.0.0p247 :017 > !!a
=> true
2.0.0p247 :018 > !!("ad" && nil && "sdf")
=> false
Но это не очень хорошее решение. Попробуйте вместо этого использовать логические типы.