6

假设我有类似的东西

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 要么返回最后一个值,要么返回它找到的第一个假值。为什么这样做?这是一个正确的心理模型吗?

4

2 回答 2

10

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

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

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

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

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

您可能想知道为什么表达式的值没有转换为trueor false; 实际上,这种行为可以用在像这样的成语中

x = x || default

或更简短的

x ||= default

用于检查是否xnil,在这种情况下,为其分配一个默认值。

于 2014-03-28T15:30:46.840 回答
1

是的,它返回最后的评估值。如果需要,您可以转换布尔值:

2.0.0p247 :016 > a = "s"
 => "s" 
2.0.0p247 :017 > !!a
 => true 
2.0.0p247 :018 > !!("ad" && nil && "sdf")
 => false

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

于 2014-03-28T15:19:34.203 回答