to_proc メソッドはProcオブジェクトに用いられるメソッドですが、シンボルでもこのメソッドを使う事ができます。
※)Procオブジェクトの説明は省略。
シンボルをProcオブジェクトにする
以下シンボルにto_proc メソッドを用いた例になります。
split_proc = :split.to_proc
puts split_proc #出力 #<Proc:0x000000000472a660(&:split)>
シンボル「:split」がProcオブジェクトになっている事がわかります。
シンボル名についてですが、任意の名前にせずに必ず「split」にしておいて下さい。
理由は後から解ります。
引数を1つ渡してみる
シンボル「:split」を変換してできたProcオブジェクトに引数を1つ渡して実行してみます。
split_proc = :split.to_proc
puts split_proc.call('a-b-c d')
#出力 ['a-b-c', 'd']
上記の出力結果から解るように「splitメソッド」の実行結果となります。
以下はシンプルに「splitメソッド」での実行です。
puts ("a-b-c d").split
#出力 ['a-b-c', 'd']
同じ出力結果になります。
この結果から、
シンボルを変換してできた Proc オブジェクトに引数を1 つ(’a-b-c d’)渡して実行すると、その引数をレシーバ にして、そのレシーバ に対して元のシンボル(:split)と同じ名前のメソッド(split)を呼び出します。
もう少し解り易く言うと、今回の場合では、
引数(’a-b-c d’)をレシーバにして、シンボル(:split)と同じ名前のメソッド(splitメソッド)を呼び出します。
最初の方に「シンボル名は任意にせずに必ず「split」にしておいて下さい。」と言ったのはこの事です。
もし、シンボル名を「:upcase」にすれば以下のようになります。
upcase_proc = :upcase.to_proc
puts upcase_proc.call("a-b-c d")
# 出力 'A-B-C D'
引数を2つ以上渡してみる
引数を2つ渡すと、第1引数はレシーバ のままですが、第2引数がシンボルで指定したメソッド(splitメソッド)の第1引数になります。
split_proc = :split.to_proc
puts split_proc.call("a-b-c d", "-")
# 出力 ["a", "b", "c d"]
引数を3つ渡すと、3つめの引数 がシンボルで指定したメソッドの第2引数になります。
split_proc = :split.to_proc
puts split_proc.call("a-b-c d", "-", 2)
# 出力 ["a", "b-c d"]
シンボルからProc オブジェクトを作成 した場合は実行時の第1引数がメソッドのレシーバ に、第2引数以降がメソッドの引数になります。また、シンボル自身はレシーバ に対して呼び出すメソッドの名前になります。
メソッドの引数としてProc オブジェクトを使う
以下をご覧ください。
puts ["a", "b", "c"].map(&:upcase)
#出力 ["A", "B", "C"]
mapメソッドの引数を見て下さい。
Proc オブジェクトに「&」を引数の前に付ける事で引数をブロックとして扱えるようになります。
また「&」の 役割はProc オブジェクトをブロック認識さるだけでなく、「&」の右辺のオブジェクト(シンボルの:upcase)に対してto_ procメソッドを呼び出します。
そしてその戻り値として得られたProc オブジェクトを、 ブロックを利用 するメソッド(mapメソッド)に 与えられます。
上記コードは以下のような感じになります。
ts ["a", "b", "c"].map(&:upcase.to_ proc)
上記のコードといままでの説明より、
「:upcase.to_ proc」でシンボル(:upcase)からProc オブジェクトが生成され、シンボル名(:upcase)と同じ名前のupcaseメソッドがブロックを利用 するメソッド(mapメソッド)に 与えられます。
上記コードは以下のコードと同じになります。
puts ["a", "b", "c"].map{|s| s.upcase}
#出力 ["A", "B", "C"]