block / Proc / lambda の違い
ドキュメント:
手続きオブジェクトの挙動の詳細 | Ruby リファレンスマニュアル [公式]
Proc.new | Ruby リファレンスマニュアル [公式]
Kernel.#lambda | Ruby リファレンスマニュアル [公式]
参考:
ブロック/Proc.new/lambda の違い – Qiita
ブロックと Proc と lambda と Method について | gaaamii のブログ
ブロックと Proc と、ときどき lambda | blog 紫陽花
return / next / break の違い
return
: メソッドを抜ける。return
に引数を指定するとメソッドの戻り値となる。next
: 次のループに進む。break
: ブロックから抜ける。break
に引数を指定するとブロックの戻り値となる。
参考:
break / next / redo の違い | Worth Living
How to break out from a block? – Stack Overflow
return / next / break の挙動の違い
手続きオブジェクト (Procedures Object) を生成する手段によって、内部で return
/ next
/ break
を実行した場合の挙動が異なる。
メソッド内で各手続きオブジェクトを生成して、同じメソッド内で各手続きオブジェクトに含まれる return
/ next
/ break
を実行した場合の違いは次のようになる。
return | next | break | |
---|---|---|---|
Proc.new | メソッドを抜ける | 手続きを抜ける | 例外が発生する |
proc | メソッドを抜ける | 手続きを抜ける | 例外が発生する |
lambda | 手続きを抜ける | 手続きを抜ける | 手続きを抜ける |
イテレーター | メソッドを抜ける | 次の繰り返しに進む | 手続きを抜ける (繰り返しを終了する) |
メソッド内で各手続きオブジェクトを生成して、メソッドを抜けてから各手続きオブジェクトに含まれる return
/ next
/ break
を実行した場合の違いは次のようになる。
return | next | break | |
---|---|---|---|
Proc.new | 例外が発生する | 手続きを抜ける | 例外が発生する |
proc | 例外が発生する | 手続きを抜ける | 例外が発生する |
lambda | 手続きを抜ける | 手続きを抜ける | 手続きを抜ける |
メソッド内で一時的な手続きを作成して、その内部で return
によりメソッドを抜けたい場合に proc
もしくは Proc.new
を使用する。それ以外の場合には lambda
を使用しておけば、不用意な例外発生の抑止となる。(lambda
では return
/ next
/ break
のいずれも手続きを抜ける動作となる。)
ドキュメント:
Kernel.#lambda | Ruby リファレンスマニュアル [公式]
ブロック付き呼び出し
ドキュメント:
ブロック付きメソッド呼び出し | Ruby リファレンスマニュアル [公式]
Symbol#to_proc | Ruby リファレンスマニュアル [公式]
yield
引数をブロックパラメータとして渡して、ブロックを実行する。yield *args
は block.call(*args)
と同じ働きをする。
ドキュメント:
参考:
block / proc / lambda の使いどころ – Qiita
ブロックの戻り値
def say
puts yield
end
say { "hello" }
# => prints: hello
Code language: Ruby (ruby)
yield
はブロックの戻り値を返す。
ブロックを明示的にメソッドの引数 (Proc
オブジェクト) として受け取った場合、call
(Proc
における yield
メソッドの別名) を実行することでブロックの戻り値が返される。
def say &block
puts block.call
end
Code language: Ruby (ruby)
ブロックの代わりに 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!
Code language: Ruby (ruby)
method(:hey)
の呼び出しにより hey
メソッドが、レシーバー main:Object
と結び付けられた Method
オブジェクトとなる。
method(:hey).call
# => prints: Hey!
Code language: Ruby (ruby)
method(:hey)
は、self.method(:hey)
として解釈され、mtehod(:hey).call
はトップレベルにおける self.hey
の呼び出しと等価になる。
ドキュメント:
参考:
ブロック/ブロック引数/Proc/yield をまとめてみた | Java からの Ruby on Rails 入門
yield でのコードの書き方について – teratail
イテレーターとブロック
参考:
block_given?
ドキュメント:
Kernel.#block_given? | Ruby リファレンスマニュアル [公式]
カリー化/部分適用
ドキュメント:
Proc#curry | Ruby リファレンスマニュアル [公式]
Method#curry | Ruby リファレンスマニュアル [公式]
参考:
ラップした proc にコンテキストを引き継ぐ
参考:
Wrap a Ruby function – Stack Overflow
Proc
ドキュメント:
class Proc | Ruby リファレンスマニュアル [公式]
arity
Proc
オブジェクトが受け付ける引数の数を返す。可変長引数を受け付ける場合は負の整数を返す。
- 正の整数: 指定された数の引数を受け付ける。
0
: 引数を受け付けない。- 負の整数: 可変長引数を受け付ける。必須の引数の数を
n
とすると- (n + 1)
が返される。
ドキュメント: