ProcとSymbol#to_procに関して調べた
昨日の日記で宿題にしてたto_procメソッドに関して
CodeIQで解答のある問題を使わせていただき、プログラムへの理解を深めております。 そこでto_procの処理につまずきました。
そもそもProcってなんだっけ
Procは、ブロックをオブジェクトとして扱うための道具です。受け取ったブロックを変数に代入したり、他のメソッドの呼び出し引数にすることができます。
Procの作り方
仮引数リストの最後に&で修飾された引数を配置すると、この引数に、呼び出し側のブロックを表すProcオブジェクトされます。
class SleepPerson def register_handler(&handler) #=>引数としてとったブロックを@event_handlerへ格納 @event_handler = handler end def wake_up! @event_handler.call Time.now, "Woke up" end end john = SleepPerson.new john.register_handler { | time, message| p [time, message] } #=>ブロックを引数にできる! john.wake_up! #=>[2014-01-11 14:08:53 +0900, "Woke up"]
はじめてのRubyの写経なんですが、wake_up!メソッドに3値目を足したり、john.register_handlerのブロックの値を少なくしたりすると動作がイメージしやすかった。
話を戻してto_procのおはなし
もともとは、以下のようなメソッドが原因で沼にはまったのでした。
method.inject(&:&)
これ、mapのチェーンメソッドなので&:&はブロックじゃないといけないのです。&:&がブロックということは、:&はProcオブジェクトであることが期待されるので、暗黙的にto_procメソッドが呼ばれます。これがSymbol#to_procの正体です。
まとめ
- Procはブロックをオブジェクト化する機構(おさらい)
- 引数に&をつけるとブロックを期待されるので、その場合には暗黙のto_procが入る
参考
- Rubyでメタプログラミング ~暗黙的に呼ばれるto_procメソッド
- 初めてのRuby 7.3.4 Proc