【Ruby】Procオブジェクト
「javascriptはRubyでいうところのProcのような書き方が多いんだよね〜」と村田講師から教えていただいたが、そもそもProcがわからないので今回はrubyのProcオブジェクトを学習していきます。
前提知識
procを学習する前に、いくつか頭に入れておかないといけない前提知識があるみたいで。
- Rubyの関数(メソッド)は直接変数に代入したり、他の関数に渡す事ができない。
- Rubyの関数(メソッド)を変数に代入したり、他の関数に渡すためには、関数をObject#methodでラップする必要がある。・・・①
- Object#methodでラップしたメソッドを実行させるためには、Object#callを実行させる必要がある。・・・②
- ②を別の関数に引き渡すこともできる。・・・③
def square(n)
n * n
end
sq = method(:square)・・・①
sq.call(3) # => 9・・・②
def print_func(arg, fun)・・・③
puts fun.call(arg)
end
print_func(4, sq)
# >> 16
無邪気な少年A: 関数Aを関数Bに渡したいです!
Rubyさん: じゃあこの2つの手続きを踏むといいよ
- 関数Aをmethodで囲む。
- 1で加工した関数Aを関数Bの引数に入れ、関数の中身でcallする
ブロック
do...endや{}で囲まれた塊のこと。
def print_func(arg, &fun)
puts fun.call(arg)
end
#do..endで書いた場合
print_func(4) do |n|
n * n
end
# >> 16
#ブロックで書いた場合
print_func(4) { |n| n * n }
# >> 16
yield
ブロックの説明で書いていた& + call を yieldで表現できるようになる。
def print_func(arg)
puts yield(arg)
end
#do..endで書いた場合
print_func(4) do |n|
n * n
end
# >> 16
#ブロックで書いた場合
print_func(4) { |n| n * n }
# >> 16
Procとは
ブロックをコンテキスト(ローカル変数のスコープやスタックフレーム)とともにオブジェクト化した手続きオブジェクト
何ができる?
ブロックを他の関数に渡す事ができるらしい。
ブロックをProcオブジェクトにするにはlambda
, proc
, Proc.new
, ->
の何れかを使う。
lambda { **|**n**|** n ***** n } *# => #<Proc:0x007f89a1852960@-:13 (lambda)>*
proc { **|**n**|** n ***** n } *# => #<Proc:0x007f89a18526b8@-:14>*
Proc.**new** { **|**n**|** n ***** n } *# => #<Proc:0x007f89a1852438@-:15>*
**->**n{ n ***** n } *# => #<Proc:0x007f89a1852190@-:16 (lambda)>*
それぞれが下記のような特徴を持つ
return next break
Proc.new メソッドを抜ける 手続きオブジェクトを抜ける 例外が発生する
proc メソッドを抜ける 手続きオブジェクトを抜ける 例外が発生する
lambda 手続きオブジェクトを抜ける 手続きオブジェクトを抜ける 手続きオブジェクトを抜ける
イテレータ メソッドを抜ける 手続きオブジェクトを抜ける メソッドを抜ける
以下のような感じでyieldと組み合わせてブロックを渡すもしくは代入する事ができる。
square = ->n{ n * n }・・・"->"でprocしている。
square.call(3) # => 9 ・・・callでprocを実行させる事ができる
def print_func(arg,fun)
puts fun.call(arg)
end
print_func(4, square)
# >> 16
procオブジェクトはそれ自体に名前がないため、無名関数と呼ばれる。
def print_func(arg, fun)
puts fun.call(arg)
end
print_func(4,->n{ n* n })
# >> 16
まとめ
- procオブジェクトはブロックを他の関数に渡すための無名関数
- 関数を変数に入れて実行する場合や、他の関数に渡す場合は、Object#methodでラップし、Object#callで実行させればいい。
一言
ざっくりとしかprocを知れてなかったけど、今回procを学習したおかげでこれからはrailsにスッキリとしたコードが書けるような気がしてきた!