Rubyのyieldは機能の理解が難しいので整理したいと思います。英単語のyieldは「生み出す、引き起こす」などの意味がありますが、Rubyでは一言で言うと、「他のものに取って代わられる」機能です。
yieldの仕組み
サンプルコードをみてみましょう。
def msg yield puts 'text3' puts 'text4' end msg do puts 'text1' puts 'text2' end # 実行結果 => text1 text2 text3 text4
Rubyのメソッド引数には、数値や文字列などの単体オブジェクトはもちろんですが、実はブロックを渡すことができます。yieldは「渡されているブロックと同じ働きをするメソッドのようなもの」と言えます。
上記のサンプルコードではmsgメソッドを呼び出すと、呼び出された時に渡されるブロック(puts 'text1' puts 'text2')がyieldによって呼び出されています。
yieldの意味
yieldは受け取ったブロックを実行します。
ブロックなしで呼び出すとLocalJumpErrorという例外が発生します。yieldを呼び出せるのはブロックが与えられたときだけです。
実はRubyではすべてのメソッドがデフォルトでブロック引数を受け取れるようになっています。(特に何も引数を指定しなくてもブロックを渡すことができる)
ブロックとは、Rubyの場合{}やdo ~ endで囲われている部分のことを指します。
サンプルコードでは引数部分を省略していますが、省略せずに書くと次のようになります。
procでブロック引数を明示します。
def msg(&proc) yield puts 'text3' puts 'text4' end msg do puts 'text1' puts 'text2' end # 実行結果 => text1 text2 text3 text4
Rubyではブロックをオブジェクトとみなさないため、あえてprocオブジェクトとして扱うことで引数として受け渡しが可能となっています。yieldではなく、procを使って書くと次のようになります。
def msg(&proc) proc.call puts 'text3' puts 'text4' end msg do puts 'text1' puts 'text2' end # 実行結果 => text1 text2 text3 text4