【问题标题】:Logic OR / AND term evaluation order in RubyRuby 中的逻辑 OR / AND 术语评估顺序
【发布时间】:2021-03-05 18:10:33
【问题描述】:

在 Ruby 中,对于二元逻辑运算符 AND 和 OR,术语的求值顺序是什么,即在类似指令中

if bool1 || bool2

首先检查哪个布尔值?正如直觉所暗示的那样,它是从左到右吗?如果第一个已经为真(或者在 AND 的情况下为假),是否需要检查两者?

这在需要检查 2 个条件时特别有用,但我们只对验证第二个条件(例如,更消耗资源的检查)真正感兴趣,前提是第一个条件失败。

搜索此信息通常会导致运算符优先级表和特别是运算符关联性,但正如您所见,这不是我要查找的内容。

【问题讨论】:

  • Ruby 使用短路评估,因此它评估第一个参数以决定是否应该继续使用第二个参数。
  • Ruby 主义者经常编写依赖于从左到右、短路求值的代码,例如 result = obj.is_a?(Hash) && obj[k]
  • 值得注意的是,当使用| 而不是|| 时,双方都在进行评估。有关示例,请参见 TrueClass#|

标签: ruby operators boolean-logic


【解决方案1】:

Ruby社区常用的是short-circuit评估,即&&代表AND||代表OR

这意味着在有两个条件的条件语句中,只有当第一个条件不足以确定表达式的值时,才会评估第二个条件

让我们以&&||为例

def a
  puts 'a method'
  false
end

def b
  'b method'
   true
end

a && b
# 'a method'
# => false

b 永远不会被评估

def a
  puts 'a method'
  true
end

def b
  'b method'
   false
end

a || b
# 'a method'
# => true

b 也从未被评估过

还有另一个构造 and, or(小写)

and 和 or 关键字在 Ruby 中的作用相同。正确理解,and 和 or 是控制流运算符,而不是布尔运算符。

您将它们用作更像控制流运算符ifunless。这个操作有很low operator precedence

延伸阅读:
and or and short-curcuit difference
short-curcuit

【讨论】:

  • 仅从示例中,尚不清楚是否评估了 b。为了清楚起见,您可以将 ab 转换为在返回值之前输出某些内容的方法——不输出,不评估。
【解决方案2】:

如果您查看ISO/IEC 30170:2012 Information technology — Programming languages — Ruby specification 的第 11.2.4 节 逻辑与表达式 和 11.2.5 逻辑或表达式 子条款 b),很容易看出评估是从左到右并且在右操作数中是惰性的(这里以||为例):

  1. 评估表达式运算符-OR-表达式。让 X 为结果值。
  2. 如果 X 是一个虚假对象,请评估 keyword-NOT-expressionoperator-AND-expression。令 Y 为结果值。 keyword-OR-expressionoperator-OR-expression的值为Y
  3. 否则,keyword-OR-expressionoperator-OR-expression的值为X

你也可以自己看看:

(p('left'); :left) || (p('right'); :right)
# left
#=> :left

(p('left'); :left) || (p('right'); false)
# left
#=> :left

(p('left'); nil)   || (p('right'); :right)
# left
# right
#=> :right

(p('left'); nil)   || (p('right'); false)
# left
# right
#=> false


(p('left'); :left) && (p('right'); :right)
# left
# right
#=> :right

(p('left'); :left) && (p('right'); false)
# left
# right
#=> false

(p('left'); nil)   && (p('right'); :right)
# left
#=> nil

(p('left'); nil)   && (p('right'); false)
# left
#=> nil

【讨论】:

  • 感谢您分享此信息。不幸的是,Ruby ISO 规范位于付费墙后面(目前约为 200 美元),因此对于许多程序员来说是遥不可及的。
猜你喜欢
  • 2013-04-10
  • 1970-01-01
  • 1970-01-01
  • 2012-01-18
  • 1970-01-01
  • 2017-08-05
  • 2020-07-22
  • 2013-03-11
  • 2013-05-16
相关资源
最近更新 更多