Ruby Kernel.raise method throws error when enclosing parameters in parenthesis

烂漫一生 提交于 2019-12-20 04:49:01

问题


I like method parameters enclosed in parenthesis, this is some Pascal nostalgia. When cleaning up code, if I find a method parameters without it I enclose them immediately. Today it caused my working code throwing errors although my syntax looks okay according to the documentation.

Kernel.raise's documentation has this format:

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

These are all working:

> raise TypeError
TypeError: TypeError

> raise (TypeError)
TypeError: TypeError

> raise "Error message"
RuntimeError: Error message

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

But the enclosed version of the next throws syntax error:

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

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

I can live without it, I just want to know why this ends with an error.


回答1:


You probably already know that in idiomatic Ruby one would never insert a space between the end of a method and an argument list in parenthesis. Some style guides explicitly forbid it.

There's a pragmatic reason too.

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 ')'

You'll encounter errors calling any method this way, not just Kernel.raise.

I'm not familiar with Ruby internals, but I would imagine the reason for this is that when a space precedes the argument list, Ruby is expecting the "no-parens" style. So of course this works:

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

Presumably Ruby is trying to evaluate the contents of each parenthesized expression before passing the result to the method. I'd speculate that writing raise (TypeError, "Error message") is asking Ruby to evaluate just TypeError, "Error message", which of course fails.




回答2:


Parentheses are used for expression grouping and precedence override in Ruby. So, when you say

foo (bar, baz)

You are sending the message :foo with a single argument which is the result of evaluating the expression bar, baz. And bar, baz is not a valid expression, therefore you get a SyntaxError.

foo (bar)

works, because bar is a valid expression.

foo (if bar then baz else quux end)

would work, too.

If you want Ruby to interpret parentheses not for expression grouping but for passing multiple arguments along with a message send, the opening parenthesis needs to directly follow the message selector:

foo(bar, baz)

This has nothing to do with Kernel#raise, BTW. You cannot change the syntax for message sends in Ruby (in fact, you cannot change any syntax in Ruby), therefore whatever is true for Kernel#raise must also be true for every other method.



来源:https://stackoverflow.com/questions/9939835/ruby-kernel-raise-method-throws-error-when-enclosing-parameters-in-parenthesis

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!