为什么Ruby块没有必需的参数?

时间:2013-04-21 21:13:22

标签: ruby

从Ruby 2.0开始,我创建了一个使用新关键字参数的小脚本。编码时,块和lambdas的行为让我感到惊讶。下面练习我发现的内容:

def print_parameters(proc = nil, &block)
  p "Block: #{block.parameters}" if proc.nil?
  p "Lambda: #{proc.parameters}" unless proc.nil?
end

print_parameters(-> (first, second = 'test') {})
print_parameters(&-> (first, second = 'test') {})
print_parameters {|first, second = 'test'|}

结果如下:

"Lambda: [[:req, :first], [:opt, :second]]"
"Block: [[:req, :first], [:opt, :second]]"
"Block: [[:opt, :first], [:opt, :second]]"

为什么创建一个块没有必需的参数但使用lambda或从lambda创建的块呢?

2 个答案:

答案 0 :(得分:2)

Ruby中块的语义旨在使它们对迭代器尽可能有用,例如Integer#timesEnumerable#each。由于块没有必需的参数,您可以执行以下操作:

10.times { puts "Hello!" }

...或:

10.times { |i| puts i }

这也是Ruby中next / return区别的原因。

Ruby“lambdas”是不同的;它们没有被“优化”用作“循环体”(尽管你可以这样使用它们)。他们对传递的参数数量更加严格,这可能有助于捕获错误。

答案 1 :(得分:0)

lambdas的行为更像ruby中的方法:当你定义一个方法时,如果需要参数,那么在调用该方法时你必须提供参数。块的行为更像procsprocs可以声明参数,但它们不需要它。

lambda语法实际上会创建具有刚性arity的proc。如果你输出两个变量的类,你会发现lambda和blocks都是Proc的实例。使用lambda语法创建的proc将对#lambda?方法作出响应。还要查看这个SO讨论,以了解lambdas和procs之间的其他一些行为区别。 When to use lambda, when to use Proc.new?