Ruby 如果| |的优先级高于=,那么为什么'a | | a=b'起作用?

Ruby 如果| |的优先级高于=,那么为什么'a | | a=b'起作用?,ruby,Ruby,我理解|和或或&和和之间的区别,但我不理解的是: 考虑一个返回@var值的方法,如果@var为nil表示false,则对其进行初始化 由于我来自JavaScript背景,我会这样写,因为|的优先级高于=: def some_method @var || (@var = MyClass.new) end 或者使用或,因为或的优先级较低: def some_method @var or @var = MyClass.new end 或者更简洁地说: def some_method @

我理解
|
&
之间的区别,但我不理解的是:

考虑一个返回
@var
值的方法,如果
@var
为nil表示false,则对其进行初始化

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

def some_method
  @var || (@var = MyClass.new)
end
或者使用
,因为
的优先级较低:

def some_method
  @var or @var = MyClass.new
end
或者更简洁地说:

def some_method
  @var ||= MyClass.new
end
但碰巧这个版本也能工作:

def some_method
  @var || @var = MyClass.new
end
我在网上搜索,但没有找到有用的结果

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

运算符优先级表明确指出,
|
的优先级高于
=

我甚至可以做
a=b | | c=d
,Ruby认为这是
a=(b | |(c=d))

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

p.S.CoffeeScript也有同样的行为

更新/澄清:此问题与短路评估无关。但是关于运算符优先级。请让我再说一遍:


如果
| |
的优先级高于
=
,那么为什么ruby将
a | | a=b
视为
a | |(a=b)
,而不是
(a | a)=b
,并引发语法错误?

短路求值法
。只有当第一个参数不足以计算表达式时,才会考虑第二个参数

在您的示例中,由于
@var
最初是
nil
,表达式的后半部分将被计算并设置为
MyClass.new
的实例


这些表达式的扩展非常有趣。有几篇博文很好地介绍了这一点。

Ruby使用所谓的
短路求值来求值这样的逻辑表达式。只有当第一个参数不足以计算表达式时,才会考虑第二个参数

在您的示例中,由于
@var
最初是
nil
,表达式的后半部分将被计算并设置为
MyClass.new
的实例


这些表达式的扩展非常有趣。有几篇博文很好地介绍了它。

我会完全忘记
。只要使用
&&
| |
,如果需要,可以使用括号

上一个示例之所以有效,是因为您使用的是实例变量。考虑一下这里的差异:

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
1.9.3>newvar
NameError:未定义的局部变量或main:对象的“newvar”方法
来自(irb):59
from/home/don/.rvm/rubies/ruby-1.9.3-p194/bin/irb:16:in`'
1.9.3>@newvar
=>零
如果尝试
newvar | | newvar=3
,则会引发错误


你可能想看看这个问题:。

我会完全忘记
。只要使用
&&
| |
,如果需要,可以使用括号

上一个示例之所以有效,是因为您使用的是实例变量。考虑一下这里的差异:

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
1.9.3>newvar
NameError:未定义的局部变量或main:对象的“newvar”方法
来自(irb):59
from/home/don/.rvm/rubies/ruby-1.9.3-p194/bin/irb:16:in`'
1.9.3>@newvar
=>零
如果尝试
newvar | | newvar=3
,则会引发错误


您可能想看看这个问题:。

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

 @var || @var = MyClass.new
没有含糊不清的地方。赋值运算符
=
只有在左侧有一个变量时才有意义(忽略多个赋值引起的复杂性)。为名为“
@var | |@var
”的变量赋值是没有意义的。因此,不存在歧义。解释上述表达式的唯一方法是将其解释为:

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

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

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

 @var || @var = MyClass.new
没有含糊不清的地方。赋值运算符
=
只有在左侧有一个变量时才有意义(忽略多个赋值引起的复杂性)。为名为“
@var | |@var
”的变量赋值是没有意义的。因此,不存在歧义。解释上述表达式的唯一方法是将其解释为:

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

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

我不知道答案,但确实让我想到了一个旧的LPC错误,您可以在那里编写
!a=1
。也许你也应该试试。这里的答案是短路。@PerJohansson
!a=1
在Ruby中工作
a
变为1,表达式的计算结果为false,带有一个
警告:found=in conditional,should=
我不知道答案,但确实让我想到了一个可以编写
的旧LPC错误!a=1
。也许你也应该试试。这里的答案是短路。@PerJohansson
!a=1
在Ruby中工作
a
变为1,表达式的计算结果为false,带有一个
warning:found=in conditional,应该是==
对不起,这没有回答我的问题。尝试将
newvar
初始化为nil,然后
将newvar | | newvar=42
。它的效果与
放置newvar=newvar | | 42
相同。请看我添加到这个问题的澄清。好的,澄清中你的问题的答案是短路,就像其他人所说的。我只是说,你上次