理解 Ruby 中赋值和逻辑运算符的优先级

7

我不理解以下示例中Ruby运算符的优先级:

x = 1 && y = 2

由于&&的优先级高于=,我的理解是类似于+*运算符:

1 + 2 * 3 + 4

这将解决为

1 + (2 * 3) + 4

应该等于:

x = (1 && y) = 2

然而,所有的 Ruby 源代码(包括内部语法分析器 Ripper)都将其解析为

x = (1 && (y = 2))

为什么?


编辑 [08.01.2016]

让我们专注于子表达式:1 && y = 2

根据优先级规则,我们应该尝试将其解析为:

(1 && y) = 2

这似乎没有意义,因为=需要一个特定的LHS(变量、常量、[]数组项等)。但由于(1 && y)是一个正确的表达式,解析器应该如何处理它呢?

我尝试过查阅Ruby的parse.y,但它太像意大利面条般复杂,我无法理解赋值的具体规则。


不错的问题,这个论点有一定的价值。 - Wand Maker
2个回答

2
简单来说,Ruby只是以一种让人容易理解的方式进行解释。 = 代表赋值。在您的期望中:
x = (1 && y) = 2

将某物分配给1 && y是没有意义的。您只能将某物分配给变量或常量。

请注意,优先级规则的目的是消除本来模棱两可的表达式的歧义。如果一种解释方式没有意义,则不需要消除歧义,因此优先级规则不会生效。


4
解析器使用规则,它没有智能来区分什么是有意义的,什么是无意义的,因此你的回答并没有提供信息。 - Rustam Gasanov
@Michael 把 1 && y 赋值给某个变量是有意义的。但把某个东西赋值给 1 && y 是没有意义的。 - sawa
1
好的,我认为你应该提到有效(用于赋值)的l-values,在这里列出了它们 http://ruby-doc.org/docs/ruby-doc-bundle/Manual/man-1.4/syntax.html#assign 。问题实际上在于 1 && y,它的计算结果为1,对于赋值是无效的。 - Rustam Gasanov
1
@sawa 我明白你的意思,很有道理。这确实不需要被评估,因为它可能产生的任何结果都不是有效的左值。已点赞。 - Rustam Gasanov
1
这与结合律有关吗?根据优先级表=具有从右到左的结合性,而&&具有从左到右的结合性。 - Wand Maker
显示剩余6条评论

0

我的理解是,在这种情况下

x = 1 && y = 2

逻辑运算符AND先被解析。然后,AND强制评估其左侧和右侧。在评估中,首先执行左侧的赋值,然后在右侧的评估中执行第二个赋值。因此,在以下情况下会出现这种情况:

x = false && y = 2

"

"y"将永远不会被赋值。当AND被触发时,强制执行x的赋值操作,但从未运行y的赋值操作,因为对于AND来说,这是不必要的。

换句话说,解析器再次只是根据我的理解聪明地识别出在运行AND时,方程式被分成左侧和右侧(方程式),然后根据运算顺序进行评估。

"

and运算符的行为与您所描述的方式相同。&&被解释为x = (1 && (y = 2))。是的,如果将1替换为false/nil,则y=赋值根本不会被解析,但这不是由于x值,而是由于内侧表达式的左侧(1 && (y=2))。 - Michael

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接