【问题标题】:Why does truth && "string" return "string"为什么真值&&“字符串”返回“字符串”
【发布时间】:2014-03-28 23:30:46
【问题描述】:

假设我有类似的东西

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 看起来要么返回最后一个值(如果全部为真),要么返回它找到的第一个假值。为什么这样做?这是一个正确的心智模型吗?

【问题讨论】:

标签: ruby truthiness


【解决方案1】:

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

因此,对涉及&& 的布尔表达式求值的更简单的心智模型是考虑仅涉及两个操作数的第一个表达式:首先计算左侧操作数;如果此操作数的值为nil 或false,则返回操作数且不计算右侧操作数;如果左边的操作数是别的,则计算右边的操作符并返回它的值。

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

作为左关联布尔运算符,很容易确定包含多个运算符的表达式的求值顺序,记住&& 的优先级高于||(但请注意and 和@ 987654329@ 具有相同的优先级)。完成此操作后,我们可以很容易地看到表达式的值是最后评估的元素,即允许确定整体 true-ness 或 false-ness 的元素表达方式。

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

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

这样的成语中
x = x || default

或更简短的

x ||= default

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

【讨论】:

  • 有趣的是x ||= default 的行为与x = x || default 不同,尽管与问题没有直接关系,因为如果x 不是nil 或false,则不会执行任何分配。然而,在不引用另一个(更常见的)习语的情况下呈现后者对我来说是不合适的。此外,我相信这种行为实际上首先是可能的,因为它首先与扩展形式一致,除了可能用于分配。
【解决方案2】:

是的,它返回最后一个评估值。您可以根据需要转换布尔值:

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

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

【讨论】:

  • 这没有回答为什么返回字符串而不是布尔值的问题。他可能已经知道如何转换为布尔值。
  • 只有第一句话是答案。
  • 不,第一句话也不是答案。问题是为什么。
猜你喜欢
  • 1970-01-01
  • 2011-11-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-09-25
  • 1970-01-01
相关资源
最近更新 更多