Почему истина && "строка" возвращает "строку"

Допустим, у меня есть что-то вроде

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

Но это не очень хорошее решение. Попробуйте вместо этого использовать логические типы.

Другие вопросы по тегам