ruby関数型プログラミング(1)Proc

rubyは関数型プログラミングをサポートする機能が用意されています。その代表的にものにProc(プロック)、yield(イールド)、lambda(ラムダ)があります。

★Proc
Procは簡単に言うと、ブロックを手続きとして扱うためのオブジェクトです。もっと簡単に言うと、Procはブロックそのものです。

コードを見た方が理解しやすいでしょう。

i = 0
p = Proc.new { i+1 }
i = 10
p.call # => 11
i = 100
p.call # => 101

callはProcオブジェクトを実行してその結果を返します。
Procで作った独自ブロックをcallで実行するわけです。
上の例の場合、Procは変数iに1加算するブロックですが、ブロックの中で変数iを使っていますのでブロックの外の変数も含まっています。この「含めて」いる対象の全体をコンテキストと呼びます。
Procは正確には、コンテキストを含むブロックをオブジェクト化した手続きオブジェクトと言えます。

またProcオブジェクトの変数の頭に&を付けて、ブロックを引数とするメソッド(以降、ブロック付きメソッドと呼びます)にProcを渡すことができます。

(1..5).map{|v| v * 10} # => [10, 20, 30, 40, 50]

は次のように書いても同じです。

p = Proc.new {|v| v * 10}
(1..5).map(&p) # => [10, 20, 30, 40, 50]


この仕組みを使って、独自のブロック(2で割り切れるときはtrue、割り切れないときは99を返す)を作ってブロック付きメソッドで処理させてみましょう。

p = Proc.new {|i|
if i % 2 == 0
 next true
end
99
}
(1..5).map(&p) # => [99, true, 99, true, 99]

next構文を使ってブロック内で手続きを中断することができます。今の場合は、2で割り切れたらnextでtrueを返しています。

このようにProcで作った独自ブロックを先頭に&をつけてブロック付きメソッドに渡し処理させることができます。

これはProcで作る独自の処理ブロックを、メソッドに渡して結果を得ることができるので、関数型プログラミングの入力と出力を実現する形の一つと言えます。

ちなみにProc.newという書き方はprocメソッドを使って次のようにも書けます。どちらのコードも同じ意味となります。

p = proc {|i|
if i % 2 == 0
 next true
end
99
}
(1..5).map(&p)


この記事が気に入ったらサポートをしてみませんか?