2011年05月29日 [長年日記]
■ メタプログラミングRubyの写経 第3章 ブロック
第3章 ブロック
呼び出し可能オブジェクトから続けました
コードを保管して、あとで呼び出す
- Proc オブジェクト
- 遅延評価
inc = Proc.new { |x| x + 1 } # なんらかの処理 inc.call(2) # => 3
- ブロックをProcに変換 lambda(),proc()
dec = lambda { |x| x - 1 } dec.class # => Proc dec.call(2) # => 1
lambda(),proc(),Proc.new()は基本的に自分の好きな物を使えば いいと書いてある。僕は
Proc.new
がしっくりくるようです。
&修飾
yield を使ってブロックを実行するけどyieldでは足りない場面が二つ
- 他のメソッドにブロックを渡したいとき
- ブロックをProcに変換したいとき
- Proc をブロックに戻したいときにも使う
Proc 対 lambda
"Proc と lambda の違いは、おそらく Ruby でもっともややこしいところだろう"
との記述がありました。自分も普段ここらへんを避けがちなのもややこしくてよくわからん ということにとても納得。
"特別な場合がたくさんあるし、独断的で根拠のない区分もたくさんある。そんな流血現場にわざわざ立ち入る必要はない。しかし、大雑把でもいいから、違いを知っておく必要がある"
との記述がある。全くその通りだ...。この本に出会えたので最低限のことは理解したい。
"Proc と lambda には二つの違いがある。一つは、return キーワードに関する事。もう一つは、引数のチェックに関する事"
- Proc と lambda と return
lambda では、return は単に lambda から戻るだけ。Proc の return は Proc から戻るのではなく、Proc が定義されたスコープから戻る
def another_double p = Proc.new { return 10 } result = p.call return result * 2 # unreachable code! end another_double # => 10
- Proc と lambda と arity(項数)
p = Proc.new {|a, b| [a, b]} p.arity # => 2
lambda のほうが Proc よりも引数の扱いに厳しい。項数を間違えてlambdaを呼び出すとArguentErrorになる。Procは引数を期待値に合わせてくれる。
p = Proc.new {|a, b| [a, b]} p.call(1,2,3) # => [1,2] p.call(1) # => [1, nil]
- Proc 対 lambda:ジャッジメント
- lambda の方がメソッドに似ているので、Procよりも直感的
- 項数に厳しく、return を呼ぶと終了してくれる。
- Rubyist の多くはProc の機能が必要でない限り、lambdaを最初に選ぶよう
どうやら僕はlambdaに慣れたほうが良さそうだ。
DSL を書く
def event(name) puts "ALERT: #{name}" if yield end Dir.glob('*events.rb').each {|file| load file } event "an event that always happens" do true end event "an event that never happens" do false end
true のだけ実行される
やっぱ複雑だのー。でも最後のDSLでの使い方は覚えておいて何かしらの機会に使いたい。