Ruby で Proc オブジェクトとブロックは似ていますが、まったく同じものではありません。むしろ、表裏一体の関係にあるというべきでしょう。その証拠に、「&」を使ってブロックから Proc へ、また Proc からブロックへとお互いに変換することができます。
まず、ブロックから Proc へ。
$ pry [1] pry(main)> def a(&block) [1] pry(main)* block [1] pry(main)* end => :a [2] pry(main)> b = a {puts "block"} => #<Proc:0x0055b7609c9d30@(pry):4> [3] pry(main)> b.call block => nil
ここではメソッド a は、与えられたブロックを Proc に変えてそのまま返します。つまり、ブロック {puts "block"}
が Proc に変換されて変数 b に入っています。なので、b を call してやるとブロックの中身が実行されて文字列 "block" が標準出力されます。このように、ブロックをオブジェクトとして取り出すことができます。
逆をしてみます。Proc からブロックへの変換の例。
$ pry [1] pry(main)> a = proc {|x| x.chomp.upcase} => #<Proc:0x0055a9370c41e0@(pry):1> [2] pry(main)> ["a\n", "b\n", "c\n"].map(&a) => ["A", "B", "C"]
ここで、変数 a に入っている Proc オブジェクトは、&a で変換されて map のブロックとして使われています。つまり、map {|x| x.chomp.upcase}
と同じことです。
以上、Proc とブロックの相互変換についてでした。