ブロック・Proc・Lambda
かつて(5年くらい前?)はまったくわからなかったブロックです.
しばらくRubyから離れて,JSで非同期処理のコールバックを扱うようになって,またRubyを始めて(,以前も現在も趣味ですが),そうしたら理解できたと思うので備忘録も兼ねてまとめた.
Ruby
Ruby: 2.2.2
ブロックの例
メソッド側は,明示的に受け取る仮引数とかは用意しない.
ブロックは yield で実行する.ブロックが引数を受け取る場合(例の場合 s )は yield に渡す.
ブロックが与えれたかは block_given? で true/false でチェックする.つまりブロックは1つしか与えられない.
def say(s)
yield "Nice to meet you, #{s}" if block_given?
end
puts "ブロックの例"
say do |s|
puts s
end
Proc
ブロックではなく Proc である.故にブロックと同じ使い方はできないが,似ている.とても似ている.
ブロックは変数に保存できないが, Proc はそれが出来る.なのでブロック使いまわしたいなあなんて時は Proc を使う.
Proc の実行は,Procオブジェクトの call メソッドを呼ぶ.
# Proc
## Procの実行方法
p = proc do |s|
puts s
#return # NG: かつては return 命令は可能だったようだが.
#s # OK
#next # OK
next s # OK: if分岐等で呼び出し元に値を返したい場合これが良い
end
val = p.call "Hello, Proc" # => "Hello, Proc"
puts "Proc returns: #{val}" # => "Proc returns: Hello, Proc"
## Procをメソッドの引数として渡す方法
def do_block(block)
block.call "Yes!"
end
p = proc do |s|
puts "私はProcです.#{s}"
end
do_block(p) # => "私はProcです.Yes!"
Lambda(ラムダ)
Lambda は Proc とほぼ同じだが,基本的に return なのでうれしい気がする.
一般的には Proc と Lamdba のどちらなのだろう?
## Lambdaの実行方法
l = lambda do |s|
puts s
return s
end
val = l.call "Hello, Lambda" # => "Hello, Lambda"
puts "Lambda returns: #{val}" # => "Lambda returns: Hello, Lambda"
## Lambdaを引数として渡す方法
l = lambda do |s|
puts "私はLambdaです.#{s}"
end
do_block(l) # => "私はLambdaです, Yes!"
# Rubyはダックタイピングなので do_block で Proc も Lambda も扱える! Nice!
lambda の別記法
Lambda には別に記法がある.
なんの役に立つのかは知らない.
l = -> (s) do
puts s
return s
end
val = l.call "Hello, Another Lambda" # => "Hello, Another Lambda"
puts "Another Lambda returns: #{val}" # => "Another Lambda returns: Hello, Another Lambda"
まとめ
ブロック・Proc・Lambdaを理解してたのしいRubyライフ!