web-dev-qa-db-ja.com

ラムダをブロックとして渡す

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

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

ただし、次のエラーが表示されます。

 ArgumentError:引数の数が間違っています(1が0)
 from code.rb:23:in `each '

ここで何が起こっているのでしょうか?

56
heneryville

アンパサンド(&)引数に、たとえば:

("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
70
numbers1311407

トリックは、必要に応じてRubyにこの引数をProcに変換し、オブジェクトをメソッドのブロックとして使用するように指示する&を使用することです。 Ruby 1.9ラムダ(匿名)関数のショートカットがあります。したがって、次のようなコードを書くことができます。

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

配列の各要素を取り、そのパワーを計算します

次のコードと同じです。

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

for 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

ラムダ関数をreduceに渡すのは少し難しいですが、匿名ブロックはラムダとほとんど同じです。

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

または、次のように文字を連結できます。

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

小文字に変換:

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

メソッド定義のコンテキストでは、最後のパラメーターの前にアンパサンドを置くことは、メソッドがブロックを取る可能性があることを示し、メソッド本体内でこのブロックを参照する名前を与えます。

21
Tombart

他の答えは、私が拡張したいことをはっきりさせていない何かを残しました。 argとブロックをメソッドに渡す方法は?

Argとブロックを受け取るメソッドがあるとします:

def method_with_arg_and_block(arg)
  puts arg
  yield
end

およびproc:

pr = proc { puts 'This is a proc'}

答え:procをメソッドに追加するのではなく、アンパサンド付きの引数としてprocを渡すことが重要です(ブロックで行うように)。

たとえば、次の場合:

method_with_arg_and_block('my arg') &pr

「ブロック指定なし(収量)」例外が発生します。

これを呼び出す正しい方法は次のとおりです。

method_with_arg_and_block('my arg', &pr)

Rubyは、procをブロックに変換し、メソッドに追加します。注:ラムダもプロシージャであるため、これはラムダでも機能します。

https://medium.com/@sihui/proc-code-block-conversion-and-ampersand-in-Ruby-35cf524eef55 に感謝します。

1
dansteren