This article提供了一个很好的概述的差异。
为了总结文章,Ruby允许隐式和显式块。而且,Ruby有block,proc和lambda。
当你调用
def foo(block)
end
block
是方法的只是一个简单的说法。参数在变量block
中被引用,并且您如何与它进行交互取决于您传递的对象的类型。
def foo(one, block, two)
p one
p block.call
p two
end
foo(1, 2, 3)
1
NoMethodError: undefined method `call' for 2:Fixnum
from (irb):3:in `foo'
from (irb):6
from /Users/weppos/.rvm/rubies/ruby-2.1.5/bin/irb:11:in `<main>'
foo(1, Proc.new { 1 + 1 }, 3)
1
2
3
但是,当你在方法定义使用符号&
,块总是有不同的含义。你是明确定义一个方法来接受一个块。而其他规则将适用(例如每个方法不超过一个块)。
def foo(one, two, &block)
p one
p block.call
p two
end
首先,作为一个块,方法签名现在接受“两个参数和一个块”,而不是“三个参数”。
foo(1, 2, Proc.new { "from the proc" })
ArgumentError: wrong number of arguments (3 for 2)
from (irb):7:in `foo'
from (irb):12
from /Users/weppos/.rvm/rubies/ruby-2.1.5/bin/irb:11:in `<main>'
这意味着,你必须强制第三个参数是传递参数与和符号的块。
foo(1, 2, &Proc.new { "from the proc" })
1
"from the proc"
2
但是,这是一种非常不常见的语法。在Ruby中,与块的方法是使用{}
foo(1, 2) { "from the block" }
1
"from the block"
2
或do end
一般调用。
foo(1, 2) do
"from the block"
end
1
"from the block"
2
让我们跳回到方法定义。我之前提到过,下面的代码是显式模块声明。
def foo(one, two, &block)
block.call
end
方法可以隐式接受一个块。用yield
调用隐式块。
def foo(one, two)
p yield
end
foo(1, 2) { "from the block" }
您可以检查块是使用block_given?
def foo(one, two)
if block_given?
p yield
else
p "No block given"
end
end
foo(1, 2) { "from the block" }
=> "from the block"
foo(1, 2)
=> "No block given"
,如果你申报“块”作为一个简单的参数(因此无符号),这些块相关的功能将不可用过去了,因为这只是一个非常方法的论点。
括号之前,不要把一个空间! :) – 2015-02-10 19:11:27
对不起,来自JavaScript世界的习惯:)我会在我的例子中纠正它。 – wmock 2015-02-10 19:12:45
http://ablogaboutcode.com/2012/01/04/the-ampersand-operator-in-ruby/ – user2864740 2015-02-10 19:32:09