1

||我理解and or, or &&and之间的区别and,但我不明白的是:

考虑一个返回 的值的方法,或者如果为 false 为 nil@var则初始化它。@var

由于我来自 JavaScript 背景,我会这样写,因为||它的优先级高于=

def some_method
  @var || (@var = MyClass.new)
end

或使用or,因为or优先级较低:

def some_method
  @var or @var = MyClass.new
end

或更简洁地说:

def some_method
  @var ||= MyClass.new
end

但碰巧这个版本也有效

def some_method
  @var || @var = MyClass.new
end

我在网上搜索,但没有找到有用的结果。

他们中的大多数只是说出和之间的||区别or

运算符优先级表清楚地表明||具有比 更高的优先级=

我什至可以做到a = b || c = d,而 Ruby 将其视为a = (b || (c = d)).

这种行为是记录在某处还是 Ruby 中的某种魔法?

PS CoffeeScript 也有同样的行为。

更新/澄清:这个问题与短路评估无关。但是关于运算符优先级。请让我重新表述一下:

如果||优先级高于=,那么为什么 ruby​​ 会看到a || a = bas a || (a = b),而不是看到(a || a) = b并引发语法错误?

4

3 回答 3

3

Ruby 使用所谓的short-circuit evaluation来评估这些逻辑表达式。只有当第一个参数不足以评估表达式时,才会考虑第二个参数。

在您的示例中,因为@varis 最初nil,表达式的后半部分被评估并设置为MyClass.new.

这些表达式的扩展非常有趣。这里这里有一些博客文章很好地涵盖了它。

于 2013-02-03T17:15:02.337 回答
2

仅当表达式中存在歧义时,优先级才会成为问题。的情况下:

 @var || @var = MyClass.new

没有歧义。赋值运算符=只有在它的左侧有一个变量时才有意义(忽略多重赋值产生的复杂性)。将某些东西分配给名为“”的变量是没有意义的@var || @var。因此,没有歧义。解释上述表达式的唯一方法是将其解释为:

 @var || (@var = MyClass.new)

因此,优先级在这里不是问题。

于 2013-02-03T17:32:10.090 回答
0

and我会完全忘记or。如果需要, 只需使用&&and ,带括号。||

您的最后一个示例仅有效,因为您使用的是实例变量。考虑这里的区别:

1.9.3> newvar
NameError: undefined local variable or method `newvar' for main:Object
        from (irb):59
        from /home/don/.rvm/rubies/ruby-1.9.3-p194/bin/irb:16:in `<main>'
1.9.3> @newvar
 => nil

如果你尝试newvar || newvar = 3它会引发错误。

你可能想看看这个 SO 问题:What does ||= (or-equals) mean in Ruby? .

于 2013-02-03T17:20:39.173 回答