Ruby力の基礎固めとして、Procについて学んだことをまとめます。
Procクラスとは
ブロックとして記述された手続きを運ぶためのクラス | たのしいRuby P415
作り方と実行の仕方
# 1
hello_1 = Proc.new do |name|
puts "Hello, #{name}" # 最後に評価される式の値が戻り値
end
# 2
hello_2 = proc do |name|
puts "Hello, #{name}" # 最後に評価される式の値が戻り値
end
hello_1.call("bob")
hello_2.call("cathy")
メソッド定義でできることならだいたいできる
- |*配列|での不定引数の受け取り
- デフォルト引数
- キーワード引数
など
lambda
Proc.newやprocで作成したProcオブジェクトよりメソッドの動きに近い動きをする
主な違いは2つある。
1 引数の数のチェック
proc = lambda do |a, b, c|
p [a, b, c]
end
proc.call(1, 2)
=> ArgumentError: wrong number of arguments (2 for 3)
2 returnの抜ける範囲
def foo
f = Proc.new { return :foo }
f.call
return
end
def foo2
f = proc { return :foo2 }
f.call
return
end
def bar
f = lambda { return :bar }
f.call
return
end
def h
yield
end
def hoge
h{ return :hoge }
nil
end
p foo()
#=> :foo
p foo2()
#=> :foo2
p bar()
#=> nil
p hoge()
#=> :hoge
return next break
Proc.new メソッドを抜ける 手続きオブジェクトを抜ける 例外が発生する
proc メソッドを抜ける 手続きオブジェクトを抜ける 例外が発生する
lambda 手続きオブジェクトを抜ける 手続きオブジェクトを抜ける 手続きオブジェクトを抜ける
イテレータ メソッドを抜ける 手続きオブジェクトを抜ける メソッドを抜ける
to_proc
メソッドにブロックを指定する際に「&オブジェクト」の形式で渡すと
オブジェクト.to_procが自動的に呼ばれる
シンボル.to_procはシンボルと同名のメソッドを呼ぶprocオブジェクトを作成する
["42", "39", "56"].map{ |i| i.to_i }
↓
["42", "39", "56"].map(&:to_i)
Procクラスの特徴
クロージャ
手続きと同時に変数などの環境を保持する手続きオブジェクトのこと
def counter
c = 0
Proc.new do
c += 1
end
end
c1 = counter
p c1.call => 1
p c1.call => 2
p c1.call => 3
c2 = counter
p c2.call => 1
p c2.call => 2
p c1.call => 4
Procクラスのインスタンスメソッド
Procオブジェクトを実行する
prc = Proc.new{|a, b| a + b}
prc.call(1, 2)
prc[3, 4]
prc.yield(1, 2)
prc.(3, 4)
prc === [9, 10]
procオブジェクトでfizzbuzz
fizz = proc{|n| n % 3 == 0 }
buzz = proc{|n| n % 5 == 0 }
fizzbuzz = proc{|n| n % 3 == 0 && n % 5 == 0}
(1..100).each do |i|
case i
when fizzbuzz then puts "Fizz Buzz #{i}"
when fizz then puts "Fizz #{i}"
when buzz then puts "Buzz #{i}"
else puts i
end
end
そのほか
prc.arity # ブロック変数の数
prc.parameters # ブロック変数の詳細
prc.lambda? # lambdaで定義されたかどうか
prc.source_location # procが定義されたソースコードの位置 (ソースファイルと行番号)
参考
- たのしいRuby
- to_proc (Symbol)