Why are parenthesis sometimes required in Ruby?

£可爱£侵袭症+ 提交于 2019-12-01 21:52:49

问题


I recently ran into an oddity while looking at some Ruby code from the Rails docs.

Ruby lets you pass arguments like these examples:

redirect_to post_url(@post), alert: "Watch it, mister!"
redirect_to({ action: 'atom' }, alert: "Something serious happened")

But that second case looked odd to me. It seems like you should be able to pass it like so:

redirect_to { action: 'atom' }, alert: "Something serious happened"

And it would have the same meaning with or without parenthesis. But instead you get:

syntax error, unexpected ':', expecting '}'

Referring to the colon after action. I'm not sure why it would be expecting } there, and why using parenthesis would change that.


回答1:


Because { ... } has two meanings: hash literal and block.

Consider this:

%w(foo bar baz).select { |x| x[0] == "b" }
# => ["bar", "baz"]

Here, { ... } is a block.

Now imagine that you are calling a method on the current object, so the explicit receiver is not needed:

select { |x| x[0]] == "b" }

Now imagine that you don't care about the parameter:

select { true }

Here, { true } is still a block, not a hash. And so it is in your function call:

redirect_to { action: 'atom' }

is (mostly) equivalent to

redirect_to do
  action: 'atom'
end

and it is nonsense. However,

redirect_to({ action: atom' })

has an argument list, consisting of a hash.




回答2:


Curly braces serve double-duty in Ruby. They can delimit a hash, but they can also delimit a block. In this case, I believe your second example is getting parsed as:

redirect_to do
  action: 'atom' 
end, alert: "Something serious happened"

Therefore your action: 'atom', which is not valid as an independent expression, gets parsed as such.

The parentheses serve to disambiguate the {...} as a hash.



来源:https://stackoverflow.com/questions/33602788/why-are-parenthesis-sometimes-required-in-ruby

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