Rubyのブロックについて
Rubyのメソッド呼び出し時には、ブロックというコードの塊を渡すことができる。メソッドにブロックを渡すにはdo end
または{ }
を使う。
オブジェクト.メソッド do |ブロックパラメータ| # ブロック end
オブジェクト.メソッド{|ブロックパラメータ| # ブロック }
ブロックをオブジェクト化したものがProc
オブジェクトである。Proc
オブジェクトは実引数に&
をつけることでブロックとして渡すことができる。
proc = Proc.new{|ブロックパラメータ| #ブロック } オブジェクト.メソッド(&proc)
ブロックはメソッドから呼び出される。その際にメソッドからブロックに渡される値がブロックパラメータである。これはメソッドでいう引数に相当する。
以下はInteger#times
メソッドをブロック付きで呼び出す例である。Integer#times
は0から自身の値までの整数を順にブロックに渡して繰り返し実行するメソッドである。
5.times{|i| puts i } =begin 0 1 2 3 4 =end
Ruby 1.9ではブロックローカル変数という概念が導入された。これはブロックの中でだけ有効な変数である。
ブロックローカル変数と同名の変数がブロック外で定義されていた場合、ブロック内ではブロックローカル変数が優先され、ブロック外の変数が隠蔽される。これをシャドウイングと呼ぶ。
ブロックパラメータを;
で区切ると、以降はブロックローカル変数の宣言となる。
以下は実際にシャドウイングが発生する例である。
foo = 42 5.times{|i; foo| # fooはブロックローカル変数 foo = i # シャドウイング puts "i = #{i}, foo = #{foo}" } =begin i = 0, foo = 0 i = 1, foo = 1 i = 2, foo = 2 i = 3, foo = 3 i = 4, foo = 4 =end puts foo #=> 42