Ruby中的这个布尔语句为什么会报错?

Why does this Boolean statement in Ruby give an error?

这可能很简单,但我不明白为什么这个声明无效Ruby代码:

3.>5 || 3.>2 
SyntaxError: unexpected tINTEGER, expecting end-of-input

为什么这个是:

3.>5 || 3.> #this seems nonsensical
=> false

以及为什么在我的书中这个答案似乎给出了误导性的答案

3.>5 || 3.>(2)
=> false

然而,这个给出了 "right" 答案

3.>(5) || 3.>(2)
=> true

Ruby 是 space 敏感的,并且与本网站使用的语法突出显示不同,Ruby 在解析运算符时使用 "maximum munch"。

3.< 不同于 3. <,因为 .< 解析为 "send the < message to the integer 3."

加一个space。更好的是,永远不要留下悬空点,正因为如此,代码 3.0 < 1.

接下来,3.>5 || 3.>(2) 解析为 3.>(5 || 3.>(2)),因为 Ruby 神奇的消失括号。遵循您的风格指南,并在几乎所有二元运算符周围添加 space。少数不应该使用的惯用语是 ..&..** 等...

这里的混淆是由于使用 . 使 Ruby 将比较解析为方法调用,而不是更正常的二元运算符,例如 3 > 2。在 Ruby 中,诸如 > 之类的运算符最终是 handled as methods,但解析器有特殊情况允许您使用更熟悉的语法。

如果您想象在整数上有一个名为 gt 的方法,并且您使用它而不是 > 重写您的示例,那么它发生的事情可能会更清楚。

您的第一个示例 3.>5 || 3.>2 将等同于:

3.gt 5 || 3.gt 2

其中 Ruby 试图解析为

3.gt (5 || 3.gt) 2

最后那个2就是Ruby吐槽的unexpected tINTEGER

第二个示例,3.>5 || 3.> 将被解析为如下内容:

3.gt (5 || 3.gt)

这似乎是荒谬的,因为我们知道 gt 实际上是二元运算符 > 并且它应该有第二个运算符。由于 Ruby 将其解析为一种方法,因此它无法知道应该有多少个参数。就解析器所知,gt 方法可能不需要任何参数(我们可以用猴子修补 > 来不期望参数)。由于表达式 5 || 3.> 的计算短路到 53.> 部分永远不会执行,因此不会发生错误。

如果您编写相同的表达式但不使用 .,则 Ruby 解析器知道这是一个二元运算符并期望第二个运算符:

eval '3>5 || 3 >'
SyntaxError: (eval):1: syntax error, unexpected end-of-input
3>5 || 3 >
          ^

最后一个示例 3.>(5) || 3.>(2) 将被解析为:

3.gt(5) || 3.gt(2)

因为括号没有歧义,很明显 2 是方法调用的参数,所以你得到了正确的答案。