【一人 Ruby Advent Calendar 2017】ブロックについていろいろ【4日目】
一人 Ruby Advent Calendar 2017 4日目の記事になります。
ちょっと遅れてしまい申し訳ありません。
さて、今回は Ruby といえばブロック、ブロックといえば Ruby ぐらいに Ruby の特徴的な機能の1つであるブロックについて書いてみます。
ブロックとは
Ruby ではメソッドに対して『任意の処理』を渡す手段とし『ブロック引数』という特別な引数があります。
メソッドでブロック引数を受け取る場合、最期の変数名に &
を追加して受け取ることができます。
# a, b は通常の引数 # &block はブロック引数 def func a, b, &block end
また、ブロック引数は必ず Proc
オブジェクトになります。
ブロック引数の渡し方
ブロック引数は通常 do 〜 end
もしくは {}
でブロックした『処理』を『Proc
オブジェクトとして』渡します。
def func &block # block は Proc オブジェクト p block # => #<Proc:0x0000000000b55888@/tmp/vtKnROY/351:10> # Proc#call で処理を呼び出す block.call 1, 2 end # func 内の block.call で {} 内の処理が呼び出される # a, b, は block.call の引数 p func { |a, b| a + b } # => 3 # 以下のような渡し方でもおk # func do |a, b| # a + b # end
このようにブロック引数を使用することでコールバック関数のような処理を実現することができます。
以下のように Proc
オブジェクトを引数として渡すこともできますが、
def func block # Proc#call で処理を呼び出す block.call 1, 2 end # proc {} をコールバック関数として渡しているが… p func(proc { |a, b| a + b }) # => 3
Ruby ではブロックを利用したほうが簡潔に記述することができますね(まあ proc
自体も引数としてブロックを受け取っているのですが。
また、ブロック引数は1つだけしか受け取ることができません。
# Error def func &block1, &block2 # end
ブロックの使用例
Ruby ではブロックがあちこちで使われていますが、例えば次のようなイテレーションメソッドでも利用されています。
# 配列の要素を選択する処理をブロックで記述する p [1, 2, 3, 4, 5, 6].select { |it| # 偶数のみ選択する it % 2 == 0 } # => [2, 4, 6] # 配列の要素を変更する処理をブロックで記述する p [1, 2, 3, 4, 5, 6].map { |it| # 要素を2倍にする it + it } # => [2, 4, 6, 8, 10, 12]
このようにしてメソッドに対して簡単に処理を渡すことができます。