2011-11-17 76 views
50

我试图定义一个块,我将使用它来传递多个范围的每个方法。而不是在每个范围重新定义块,我想创建一个兰巴,并通过lambda作为这样的:将lambda作为块传递

count = 0 
procedure = lambda {|v| map[count+=1]=v} 
("A".."K").each procedure 
("M".."N").each procedure 
("P".."Z").each procedure 

不过,我得到以下错误:

 
ArgumentError: wrong number of arguments(1 for 0) 
    from code.rb:23:in `each' 

任何想法是什么去这里?

回答

65

粘性符号(&)到参数,例如:

("A".."K").each &procedure 

这意味着,要传递它作为该方法的特殊块参数。否则,它被解释为一个正常的论点。

这也反映了他们的方式你会捕捉和访问方法本身内部的块参数:

# the & here signifies that the special block parameter should be captured 
# into the variable `procedure` 
def some_func(foo, bar, &procedure) 
    procedure.call(foo, bar) 
end 

some_func(2, 3) {|a, b| a * b } 
=> 6 
12

诀窍是使用&它告诉红宝石,如果有必要这样的说法转化为Proc和然后使用该对象作为方法的块。从Ruby 1.9开始,lambda(匿名)函数有一个快捷方式。所以,你可以这样写代码:

(1..5).map &->(x){ x*x } 
# => [1, 4, 9, 16, 25] 

将采取数组的每个元素,并计算其功率

它是与此相同的代码:

func = ->(x) { x*x } 
(1..5).map &func 

为Ruby 1.8:

(1..5).map &lambda {|x| x*x} 
# => [1, 4, 9, 16, 25] 

解决你的问题,你可以使用阵列的方法reduce0是初始值):

('A'..'K').reduce(0) { |sum,elem| sum + elem.size } 
# => 11 

传递lambda函数到reduce是有点麻烦,但匿名块几乎是相同的λ。

('A'..'K').reduce(0) { |sum, elem| ->(sum){ sum + 1}.call(sum) } 
# => 11 

或者你可以Concat的信件就像这样:

('A'..'K').reduce(:+) 
=> "ABCDEFGHIJK" 

转换为小写:

('A'..'K').map &->(a){ a.downcase } 
=> ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k"] 

方法定义的情况下,把一个符号,在过去的前参数表示一个方法可能需要一个块,并给我们一个名称来引用方法体内的这个块。