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.>
的计算短路到 5
,3.>
部分永远不会执行,因此不会发生错误。
如果您编写相同的表达式但不使用 .
,则 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
是方法调用的参数,所以你得到了正确的答案。
这可能很简单,但我不明白为什么这个声明无效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.>
的计算短路到 5
,3.>
部分永远不会执行,因此不会发生错误。
如果您编写相同的表达式但不使用 .
,则 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
是方法调用的参数,所以你得到了正确的答案。