从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创建的块呢?
答案 0 :(得分:2)
Ruby中块的语义旨在使它们对迭代器尽可能有用,例如Integer#times
或Enumerable#each
。由于块没有必需的参数,您可以执行以下操作:
10.times { puts "Hello!" }
...或:
10.times { |i| puts i }
这也是Ruby中next
/ return
区别的原因。
Ruby“lambdas”是不同的;它们没有被“优化”用作“循环体”(尽管你可以这样使用它们)。他们对传递的参数数量更加严格,这可能有助于捕获错误。
答案 1 :(得分:0)
lambdas
的行为更像ruby中的方法:当你定义一个方法时,如果需要参数,那么在调用该方法时你必须提供参数。块的行为更像procs
:procs
可以声明参数,但它们不需要它。
lambda
语法实际上会创建具有刚性arity的proc
。如果你输出两个变量的类,你会发现lambda和blocks都是Proc
的实例。使用lambda语法创建的proc
将对#lambda?
方法作出响应。还要查看这个SO讨论,以了解lambdas和procs之间的其他一些行为区别。 When to use lambda, when to use Proc.new?