在括号中包含参数时,Ruby Kernel.raise方法会引发错误

我喜欢用括号括起来的方法参数,这是一些Pascal的怀旧之情。 清理代码时,如果我找到没有它的方法参数,我会立即将它们括起来。 今天它导致我的工作代码抛出错误,虽然我的语法看起来没问题根据文档。

Kernel.raise的文档具有以下格式:

(Object) raise(exception[, string [, array]]) 

这些都有效:

 > raise TypeError TypeError: TypeError > raise (TypeError) TypeError: TypeError > raise "Error message" RuntimeError: Error message > raise ("Error message") RuntimeError: Error message 

但是下一个抛出语法错误的封闭版本:

 > raise TypeError, "Error message" TypeError: Error message > raise (TypeError, "Error message") SyntaxError: unexpected ')', expecting $end 

我可以没有它,我只是想知道为什么这会以错误结束。

您可能已经知道,在惯用的Ruby中,永远不会在方法的结尾和括号中的参数列表之间插入空格。 一些风格指南明确禁止它 。

这也是一个务实的原因。

 1.9.2-p290 > def concat(a, b) 1.9.2-p290 > a + b 1.9.2-p290 > end 1.9.2-p290 > concat 'foo', 'bar' => "foobar" 1.9.2-p290 > concat('foo', 'bar') => "foobar" 1.9.2-p290 > concat ('foo', 'bar') SyntaxError: (irb):27: syntax error, unexpected ',', expecting ')' 

你会遇到以这种方式调用任何方法的错误,而不仅仅是Kernel.raise

我不熟悉Ruby内部,但我想这样做的原因是,当一个空格位于参数列表之前时,Ruby期待“no-parens”风格。 所以这当然有效:

 1.9.2-p290 :035 > concat ("bar"), ("foo") => "barfoo" 

据推测,Ruby在将结果传递给方法之前尝试评估每个带括号的表达式的内容。 我推测写入raise (TypeError, "Error message")是要求Ruby仅评估TypeError, "Error message" ,当然这会失败。

括号用于Ruby中的表达式分组和优先级覆盖。 所以,当你说

 foo (bar, baz) 

您正在发送消息:foo ,其中包含一个参数,该参数是评估表达式bar, baz 。 而bar, baz不是一个有效的表达式,因此你得到一个SyntaxError

 foo (bar) 

有效,因为bar是一个有效的表达式。

 foo (if bar then baz else quux end) 

也会工作。

如果您希望Ruby解释括号而不是表达式分组但是为了传递多个参数以及消息send,则左括号需要直接跟随消息选择器:

 foo(bar, baz) 

这与Kernel#raise ,BTW无关。 你无法改变Ruby中消息发送的语法(事实上,你不能改变Ruby中的任何语法),因此对于Kernel#raise来说,对于其他所有方法都必须如此。