1

我喜欢括号中的方法参数,这是一些帕斯卡的怀旧之情。清理代码时,如果我发现没有它的方法参数,我会立即将它们附上。今天它导致我的工作代码抛出错误,尽管根据文档我的语法看起来不错。

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

但是 next 的封闭版本会引发语法错误:

> raise TypeError, "Error message"
TypeError: Error message

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

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

4

2 回答 2

5

您可能已经知道,在惯用的 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 期待“无括号”样式。所以这当然有效:

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

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

于 2012-03-30T09:23:16.617 回答
3

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

foo (bar, baz)

您正在发送:foo带有单个参数的消息,该参数是评估表达式的结果bar, baz。Andbar, baz不是一个有效的表达式,因此你得到一个SyntaxError.

foo (bar)

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

foo (if bar then baz else quux end)

也可以。

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

foo(bar, baz)

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

于 2012-03-30T09:42:12.470 回答