block / Proc / lambda の違い

参考:

Ruby の block、Proc、lambda を理解する | このブログは証明できない。

Ruby の ブロック、Proc.new、lambda の違い – Qiita

Ruby のブロックと Proc と lambda と Method について | gaaamii のブログ

Ruby のブロックと Proc と、ときどき lambda | blog 紫陽花

手続きオブジェクトの挙動の詳細 (Ruby 2.5.0)

singleton method Proc.new (Ruby 2.5.0)

module function Kernel.#lambda (Ruby 2.5.0)

return / next / break の違い

  • return :メソッドを抜ける。return に引数を指定するとメソッドの戻り値となる。
  • next :次のループに進む。
  • break :ブロックから抜ける。break に引数を指定するとブロックの戻り値となる。

参考:

ruby の block 文での break, next – Qiita

ブロックについてのあれこれ – Qiita

ブロック内からの return | bonar note

break, next, redo の違い | Worth Living

How to break out from a ruby block? – Stack Overflow

手続きオブジェクトにおける return / next / break の挙動の違い

手続きオブジェクト (Procedures Object、以下 PO と表記) を生成する手段によって、内部で return / next / break を実行した場合の挙動が異なる。

メソッド内で各手続きオブジェクト (PO) を生成して、同じメソッド内で各手続きオブジェクトに含まれる return / next / break を実行した場合の違いは次のようになる。

return next break
Proc.new メソッドを抜ける POを抜ける 例外が発生する
proc メソッドを抜ける POを抜ける 例外が発生する
lambda POを抜ける POを抜ける POを抜ける
イテレーター メソッドを抜ける 次の繰り返しに進む 繰り返しを終了
(POを抜ける)

メソッド内で各手続きオブジェクト (PO) を生成して、メソッドを抜けてから各手続きオブジェクトに含まれる return / next / break を実行した場合の違いは次のようになる。

return next break
Proc.new 例外が発生する POを抜ける 例外が発生する
proc 例外が発生する POを抜ける 例外が発生する
lambda POを抜ける POを抜ける POを抜ける

参考:

module function Kernel.#lambda (Ruby 2.5.0)

yield

引数をブロックパラメータとして渡して、ブロックを実行する。yield *argsblock.call(*args) と同じ働きをする。

参考:

yield – メソッド呼び出し (super・ブロック付き・yield) (Ruby 2.6.0)

block/proc/lambda の使いどころ – Qiita

ブロックの戻り値

def say
  puts yield
end

say { "hello" }
# => prints: hello

yield はブロックの戻り値を返す。

ブロックを明示的にメソッドの引数 (Proc オブジェクト) として受け取った場合、call (Proc における yield メソッドの別名) を実行することでブロックの戻り値が返される。

def say &block
  puts block.call
end

ブロックの代わりに Proc オブジェクトや lambda を受け取ることができる。

メソッドが受け取るブロックは一つと決まっているので、block.call の代わりに yield と書くことができる。

def say(&proc)
  puts proc.call if block_given?
end

say{ "hello" }
# => prints: hello

hello = Proc.new{ "hello" }

say(&hello)
# => prints: hello

bye = -> { "bye" }

say(&bye)
# => prints: bye

def hey
  "Hey!"
end

say(&method(:hey))
# => prints: Hey!

method(:hey) の呼び出しにより hey メソッドが、レシーバー main:Object と結び付けられた Method オブジェクトとなる。

method(:hey).call
# => prints: Hey!

method(:hey) は、self.method(:hey) として解釈され、mtehod(:hey).call はトップレベルにおける self.hey の呼び出しと等価になる。

参考:

メソッドとブロックの戻り値 | ばくのエンジニア日誌

yield の役割 – Qiita

Ruby の yield って結局なんなの? | YNote

Ruby のブロック、ブロック引数、Proc、yield をまとめてみた | Java からの Ruby on Rails 入門

yield でのコードの書き方について | teratail

yield – メソッド呼び出し (super・ブロック付き・yield) (Ruby 2.5.0)

イテレーターとブロック

参考:

Ruby の yield が難しい。| OnsenとRuby

Ruby でのイテレータを使った繰り返し | vivid memo

block_given?

参考:

module function Kernel.#block_given? (Ruby 2.6.0)

Tagged:

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です