Ruby で Proc とブロックの相互変換について

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 とブロックの相互変換についてでした。