为什么 Ruby 中有时需要括号?

Why are parenthesis sometimes required in Ruby?

我最近 运行 在查看来自 Rails docs 的一些 Ruby 代码时感到奇怪。

Ruby 可让您像以下示例一样传递参数:

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

但是我觉得第二种情况很奇怪。看起来你应该能够像这样通过它:

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

加括号和不加括号都是一样的意思。但是你得到的是:

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

action后的冒号。我不确定为什么它会在那里期待 },以及为什么使用括号会改变它。

花括号在 Ruby 中起着双重作用。它们可以界定一个散列,但它们也可以界定一个块。在这种情况下,我相信您的第二个示例被解析为:

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

因此,您的 action: 'atom' 作为独立表达式无效,因此被这样解析。

括号用于消除 {...} 作为散列的歧义。

因为{ ... }有两个意思:hash literal和block。

考虑一下:

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

这里,{ ... }是一个块。

现在假设您正在调用当前对象的方法,因此不需要显式接收器:

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

现在假设您不关心参数:

select { true }

在这里,{ true }仍然是一个块,而不是哈希。所以它在你的函数调用中:

redirect_to { action: 'atom' }

(大部分)等同于

redirect_to do
  action: 'atom'
end

这是胡说八道。然而,

redirect_to({ action: atom' })

有一个参数列表,由散列组成。