2011-11-17 11 views
50

複数の範囲の各メソッドを渡すために使用するブロックを定義しようとしています。むしろ各範囲にブロックを再定義するよりも、私はラムダを作成したいと、そのようにラムダを渡したい:ラムダをブロックとして渡す

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のを伝え&を使用しており、オブジェクトをメソッドのブロックとして使用します。 Ruby 1.9以降、ラムダ(匿名)関数のショートカットがあります。だから、あなたはこのようなコードを書くことができます。

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

は、配列の各要素を取得し、その力を計算します

を、このコードと同じです:ルビー1.8用

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

:あなたは配列のメソッドを使用することができますあなたの問題を解決するために

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

reduce0)が初期値である:

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

reduceにラムダ関数を渡すは少しトリッキーですが、無名ブロックはかなりラムダと同じです。

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

それとも、ただ、このように文字をCONCAT可能性:最後の前にアンパサンドを入れて、メソッド定義の文脈では

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

:小文字に

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

変換パラメータはメソッドがブロックを取ることを示し、メソッド本体内のこのブロックを参照する名前を与えます。

関連する問題