This is IT

技術、日常

yieldとblock.callの処理の実行フローを理解する

概要

下記は、yieldを使ったコード。

def greet
  puts "横浜の塩"
  yield
  yield
  puts "話を聞け"
end

greet do |txt|
  puts "俺の"
end

#=>横浜の塩
#=>俺の
#=>俺の
#=>話を聞け

yieldで、メソッド呼び出しのブロック内の処理が実行されることが分かる。

一方で、こちらのコードはどうだろうか?

def greet
  puts "横浜の塩"
  text = yield "俺の"
  puts text
  puts "話を聞け"
end

greet do |text|
  text * 2
end

#=>横浜の塩
#=>俺の俺の
#=>話を聞け

ん~・・。

 text = yield "俺の"

の部分があまり分からない。

なので、ここをちゃんと理解してみよう、というお話。

実行フロー

① メソッドを呼び出す

② メソッド内のyieldが呼ばれる

③ 呼び出した側のブロックに処理をしてもらう

という流れだが、③の際に引数を渡すこともできる。

大元の実行フローは変わらないので、この順序に沿って今回のコードを見てみる。

def greet
  puts "横浜の塩"
  text = yield "俺の" 
  #...
end

# メソッドを呼び出す
greet do |text|
  text * 2
end

①「gree do |text| ~ end」ではブロック付きで、『greet』メソッドを呼び出す

② メソッド内の2行目でyieldが呼び出される

③ 呼び出した側「gree do |text| ~ end」のブロックに処理をしてもらう

という流れになる。

今回はさらに、

④ ③の際に、ブロックパラメータに"俺の"を渡す

⑤ 結果、「gree do |text| ~ end」の戻り値、つまりyield "俺の"の値が、"俺の俺の"となる。

block.callでは?

def greet(&block)
  puts "横浜の塩"
  text = block.call("俺の")
  puts text
  puts "話を聞け"
end

greet do |text|
  text * 2
end

yieldと実行フローは全く同じ。 Procオブジェクトを引数にするときは&を付けること、また、ブロックの処理をしてもらうときは、callメソッドを利用することに留意する。