Ruby のブロックはオブジェクト

これ、タイトルは釣りだと思うのだけれど、一応。

Ruby のブロックはもちろんオブジェクトです。Proc オブジェクトとして持ち運ぶことができます。例えば

def hoge(&bk)
  p bk
  bk.call
end

hoge do
  puts "fuga"
end

というコードがあります(むっちゃテキトーですが)。これを実行すると

#<Proc:0x005637e7cddff0@hoge.rb:6>
fuga

などと出力されます。hoge メソッドはブロックが Proc オブジェクトであることを出力し、さらにブロックを実行していることがわかると思います。なお、bk.call はここでは yield と同等です。


なお、上のリンク先の引用内の

If I ask it to tell me its class it replies "syntax error"!

というのはどういうことなのでしょうね。

p ({puts "fuga"})

ということでしょうか*1。確かにこれは syntax error になります。でもこれ、意味がないのですけれど。

p (proc {puts "fuga"})
#=>#<Proc:0x0055dc8c132568@hoge.rb:1>

とすればいいのですから。これではイカンの? インチキ? この Proc オブジェクトはブロックとして使うことができます。実際

a = proc {puts "fuga"}
hoge(&a)

は、最初の例とまったく同じ結果をもたらすのですから*2。「&」はブロックを Proc オブジェクトに、また Proc オブジェクトをブロックに変換します。

*1:p {puts "fuga"} と書かないのは、括弧内がメソッド p のブロックとして解釈されて syntax error にならないからです。Ruby のすべてのメソッドはブロックを取ることができます。処理が定義されていない場合は無視されます。

*2:自分はやりませんが、hoge(&proc {puts "fuga"}) とだって書けます。