块之前的参数的括号

时间:2014-12-21 19:44:16

标签: ruby-on-rails ruby arguments block

我注意到我需要在块之前将括号括起来传递给Ruby方法。 Wat是什么原因?归结为最小的例子来说明我的意思:

def test a
   yield 100
end

test 50 { |x| x*x + 2 } # Gives an error in irb!

test(50) { |x| x*x + 2 } # Gives no error!

我不明白为什么Ruby会抱怨第一个案例。错误如下:

SyntaxError: compile error
(irb):18: syntax error, unexpected '{', expecting $end

4 个答案:

答案 0 :(得分:3)

以下是可能出现歧义的一个例子:

def foo(val = "default", &block)
  # ...
end

哈希和块文字都是使用{ ... }

创建的

因此,如果您致电foo {} - 您是否将空哈希传递给val参数(block成为nil),或者您是否将空块传递给block参数(val成为"default")?

答案 1 :(得分:2)

这与{ ... }有时会分隔一个块,有时是一个Hash文字的事实有关。消除这两种用途的歧义有一些奇怪的副作用。

如果您使用do ... end,则无法使用括号:

test 50 do |x| x*x + 2 end

答案 2 :(得分:1)

Ruby不知道你想用块做什么。

当Ruby看到:

test 50 { |x| x*x + 2 } # Gives an error in irb!

它认为该块已附加到50,这就是您收到错误的原因。

当你将50放在括号中时,Ruby知道该块没有绑定到50

test(50) { |x| x*x + 2 } # Gives no error!

为了理智,99.9%的时间我将参数放在括号内。我不想记住绑定规则,并确保Ruby能做正确的事情。此外,括号可以帮助我们查看哪些参数有助于调试。

答案 3 :(得分:-2)

使用块表示法时,块将针对开头{左边的值运行。因此,在您的第一个示例中,您尝试将50 { |x| ... }传递给test方法。由于50不是Enumerable对象,因此您收到错误。