Ruby - 在语句中错误的断行仍然会产生结果吗?

8
精简脚本如下:
z1 = (12 -
          2) / (5)
z2 = (12
        -  2) / (5)
puts(z1.to_s + " " + z2.to_s)

这将会得到:

$ ruby rubytest.rb 
2 -1

现在,我知道z1 是正确的方法,因为行末悬挂运算符被解释为自动延续该行。
然而,我希望解释器会严格处理z2案例,并告诉我语句是不完整的,或者其第二行是无意义的。但它“很好地”处理了它并给出了“-1”的答案。它是试图表现得自信,不承认自己困惑,并希望这个错误答案不会被注意到吗?
有人能解释一下z2评估实际发生了什么,为什么是“-1”,为什么没有语法错误,并且是否有一个使用此行为的示例(或者我们应该提出请求以删除它)?

1
有趣的是将5更改为5.0,然后得到-0.4,这意味着它完全忽略了12。虽然不清楚它具体是在做什么,但是一定程度上进行了澄清。 - Philip Hallstrom
哇..真的很期待看到答案。似乎它只计算第二行的-2/5。但是,如果您在12之前使用未定义的内容,则会出现NameError。我还尝试过:(2 + <new line here> -2/5)这将使2-1=1。疯狂。 - radubogdan
有人检查过不同版本的Ruby是否返回相同的结果吗?我正在使用2.1.0。为了检查,我认为只需要在第一行上写(,在第二行上写-2)/5就足够了。 - Cary Swoveland
1
在z2中,它不会像这样读取:(12; (- 2 / 5),因为Ruby会返回最后一个被评估的东西,所以结果是-1? - Anthony
1
我想我只是在说 (12; -2) / 5 的结果也是-1,而且我相信 OP 的 z2 和这个是等价的。我刚刚发现了关于这个问题的这个有趣的信息 - Anthony
显示剩余4条评论
1个回答

12

这是一个特性,但你可能一开始会认为它是个错误。它出现的原因与你可以做到以下操作的原因相同(在许多情况下非常方便):

(call_function_1; call_function_2) if some_condition

换行符被解释为与;相同。例如,您会注意到这个表达式可以正常评估,只有最后一个表达式被返回,但所有表达式仍然被评估:

(1
 2
 3
 4
 5)
=> 5

就跟

(1; 2; 3; 4; 5)
=> 5

为了查看所有表达式的求值结果,你可以尝试以下示例:

(puts "A"
 puts "B"
 puts "C"
 123)
A
B
C
=> 123

所以你的示例变成了:

(12; -2) / 5

这与以下内容相同:

-2 / 5

这是 -1

要让 Ruby 把 12 解释为未完成的语句而不是单独的语句,您可以通过添加一条行继续提示符\ 来告诉 Ruby:

(12 \
 - 2) / 5
=> 2

我想Ruby的某种“lint”工具应该会发现这个问题吧?(我的最初反应是这是一个有点鲁莽的设计,但经过进一步思考,它符合Ruby的一般感觉,其中语法是流畅的,人们必须比通常更加警惕换行符。这种跨越换行符的括号处理是Python程序员编写Ruby并期望语法上的表面差异的一个主要语法陷阱,但背后的思想类似。) - Evgeni Sergeev

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