RubyのブロックとProcとlambdaとMethodについて
RubyのブロックとProcとlambdaとMethodについて書きたいけど自信がないです。容赦のないマサカリやツッコミをお願い致します。
ブロック
ブロックははじめてRubyを触ったときから慣れ親しんでいるものです。
%w(:Yoshida, :Tanaka, :Suzuki).each do |name| puts "Hello, #{name}" end # または %w(:Yoshida, :Tanaka, :Suzuki).each { |name| puts "Hello, #{name}" }
do と end というキーワード、あるいは波括弧{}
で行いたい手続きを囲みます。
yield
yieldは渡されたブロックを実行します。 例として、「誰かに何かする」というメソッドを定義してみます。
def do_for(name) yield(name) end do_for(:Tanaka) { |name| puts "Hello, #{name}" } do_for(:Suzuki) { |name| puts name.upcase }
Proc
1回きりならdoとendで囲んどきゃいいけど、その手続きを変数に入れたりして保持したいこともあります。 Procクラスのコンストラクタに同じブロックを渡せば、その処理をいつでも呼び出せるようになります。
hello_proc = Proc.new { |name| puts "Hello, #{name}" } hello_proc.call :Nishikori %w(:Yoshida, :Tanaka, :Suzuki).each { |name| hello_proc.call name }
lambda
「ラムダ」と発音します。Procとほぼおなじですが、違いもあるようです。ただlambda式を実行して返ってくるものはProcクラスではあります。
hello_lambda = ->(name) { puts "Hello #{name}"} hello_lambda.call :hoge hello_lambda.class #=> Proc
Procとの違い
「Procとほぼおなじ」というからには、何か違いがあるわけですね。コメントを頂きましたのでそれをここでも共有させていただきます。
引数チェック
# Proc は引数チェックしない hello = Proc.new { |name| "Hello, #{name}" } hello.call :Tanaka, :Suzuki #=> "Hello, Tanaka" # lambda は引数チェックする hello_lambda = ->(name) { "Hello, #{name}" } hello_lambda.call :Tanaka, :Suzuki #=> ArgumentError
returnの処理
[TODO: サンプルコード]
Method
自信が無いのでドキュメントそのまま引用します。
Methodとは、
Object#method によりオブジェクト化され たメソッドオブジェクトのクラスです。
メソッドの実体(名前でなく)とレシーバの組を封入します。 Proc オブジェクトと違ってコンテキストを保持しません。
とのこと。
まとめ
利用の場面を経験しないとなんとも言えない感じがするので、Ruby熟練者が書いたコードをたくさん読んでいきたいです。
なにかいろいろ物足りないのでちょこちょこ書き直します。
参考リンク
- Ruby の Proc オブジェクトと Method オブジェクトの違い (proc, lambda, ブロック, メソッドについて) - vivid memo
- Ruby block/proc/lambdaの使いどころ - Qiita
- Procを制する者がRubyを制す(嘘)
- Ruby のキーワード一覧 - Secret Garden(Instrumental)
- Ruby の Proc オブジェクトと Method オブジェクトの違い (proc, lambda, ブロック, メソッドについて) - vivid memo