Proc/yield/&blockによるメソッドへのブロック渡し・実行方法

Ruby

メソッドにブロックを渡し、渡されたブロックをメソッド内で実行する方法には以下の3つがあります。

  • Procオブジェクトをブロック引数として渡し、メソッド内でブロック引数を利用する方法
  • ブロックをブロック引数として渡し、メソッド内でブロック引数を利用する方法
  • yieldを利用してブロックを実行する方法

今回は上記の各方法について紹介します。

Procオブジェクトをブロック引数として渡し、メソッド内でブロック引数を利用する方法

Procオブジェクトとは、Procクラスを利用してオブジェクト化されたブロックのインスタンスのことを指します。
Procオブジェクトはブロック引数を利用してメソッドに渡します。
渡されたProcオブジェクトをメソッド内で実行するにはcallメソッドを利用します。

引数なしのProcオブジェクトを利用する場合

def example(&ブロック引数)
  ブロック引数.call
end

example(&Procオブジェクト)

具体的には以下のようになります。

def message(&block)
  print "Hey "
  block.call
end

message_proc = proc {
  print "Bob"
}

message(&message_proc)
# Hey Bob

引数ありのProcオブジェクトを利用する場合

def example(引数, &ブロック引数)
  ブロック引数.call(引数)
end

example(引数, &Procオブジェクト)

具体的には以下のようになります。

def message(name, &block)
  print "Hey "
  block.call(name)
end

message_proc = proc do |name|
  print "#{name}"
end

message("Bob", &message_proc)
# Hey Bob

ブロックをブロック引数として渡し、メソッド内でブロック引数を利用する方法

ブロック引数にブロックを渡した場合、ブロックはProcオブジェクトに変換されます。1
そのため、Procオブジェクトを作成せずにブロックを直接ブロック引数としてメソッドに渡すことも可能です。

引数なしのブロックを利用する場合

def example(&ブロック引数)
  ブロック引数.call
end

example do
  # 処理
end

具体的には以下のようになります。

def message(&block)
  print "Hey "
  block.call
end

message do
  print "Bob"
end
# Hey Bob

引数ありのブロックを利用する場合

def example(引数, &ブロック引数)
  ブロック引数.call(引数)
end

example(実引数) do |仮引数|
  # 処理
end

具体的には以下のようになります。

def message(name, &block)
  print "Hey "
  block.call(name)
end

message("Bob") do |name|
  print "#{name}"
end
# Hey Bob

yieldを利用してブロックを実行する方法

メソッドで利用できるブロック引数は1つだけです。1
そのため、メソッドでブロックを実行する際はブロック変数名を明示せずとも『渡されたブロックを呼び出す』という記述があれば十分です。
yieldは『渡されたブロックを呼び出す』を呼び出すメソッドです。

block.callyieldに書き換えることでブロック引数が不要になるため、yieldを利用する場合はブロック引数を省略できます。

引数なしのブロックを利用する場合

def example
  yield
end

example do
  # 処理
end

具体的には以下のようになります。

def message
  print "Hey "
  yield
end

message do
  print "Bob"
end
# Hey Bob

引数ありのブロックを利用する場合

def example(引数)
  yield(引数)
end

example(実引数) do |仮引数|
  # 処理
end

具体的には以下のようになります。

def message(name, &block)
  print "Hey "
  yield(name)
end

message("Bob") do |name|
  print "#{name}"
end
# Hey Bob

さいごに

Twitter(@nishina555)やってます。フォローしてもらえるとうれしいです!

参考