为什么真相&&“字符串”返回“字符串”

假设我有类似的东西

true && true #=> true 

这是有道理的,所以我尝试这样的事情:

 true && "dsfdsf" #=> "dsfdsf" 

这让我感到惊讶,因为我经常会做一些事情,比如if something && somethingif 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似乎返回最后一个值。 为什么这样做? 这是一个正确的心理模型吗?

ruby中的布尔运算符是短路的 :如果可以从左侧参数确定表达式的值,则不评估右侧参数。

因此,用于评估涉及&&的布尔表达式的简单心智模型是考虑仅涉及两个操作数的第一个表达式:首先计算左侧操作数; 如果此操作数的值为nilfalse ,则返回操作数并且不评估右操作数; 如果左侧操作数是其他任何内容,则评估右侧操作符并返回其值。

根据这个定义,很明显,正如您所注意到的,涉及布尔运算符的表达式不返回truefalse ,而只返回true值false值 。 值得注意的是,这在布尔表达式仅用于其真实性假性的上下文中没有任何区别。

作为左关联的布尔运算符,很容易确定包含多个运算符的表达式的求值顺序,记住&&优先级高于|| (但要小心, and or具有相同的优先权)。 完成此操作后,我们可以很容易地看到表达式的值是最后一个被评估的元素,即允许确定表达式的整体真实性错误性的元素。

在您的示例(仅由&&运算符组成的表达式)中,只要遇到第一个false值 ,或者在将最后一个元素作为true值计算之后,就会知道表达式的 。 因此,如果前面的所有元素都是真值 ,那么最后一个元素将被评估为最后一个元素,如果遇到任何元素,则它将是第一个假值元素。

您可能想知道为什么表达式的值不会转换为truefalse ; 实际上,这种行为可以用在像习语这样的习语中

 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 

但这不是一个好的解决方案。 尝试使用布尔类型。