Procとcallメソッド
以下では、get_closureメソッドにより、クロージャオブジェクトを生成している。
その際初期値を設定している。
クロージャオブジェクトのcallメソッドによりクロージャを実行する。
初期値を設定した変数initial_valueはクロージャのスコープなので、
クロージャの外からは一切存在を管理する必要がない。
def get_closure initial_value
Proc.new{|up| initial_value += up}
end
closure = get_closure(100)
closure.call(10) # 110
closure.call(20) # 130
proc内でのreturn
proc内でreturnすると、procの呼び出し元のスコープを抜ける。
procの呼び出し位置で処理が止まるため、そのあとの処理は実行されない。
以下callerというメソッド内でprocを実行するが、
procがreturnすることで、proc.callの実行後callerのスコープを抜ける。
なので2は評価されない。
この動きは後のlambdaと異なる。
def caller
proc = Proc.new{ return 1 }
proc.call
2
end
Procオブジェクトをブロックに変換
作っておいたクロージャオブジェクトをメソッド実行時にブロックとして使用することができる。
メソッドの引数として、&を付与してProcオブジェクトを渡す。
def func hoge
hoge + yield
end
closure = Proc.new {5}
func(10, &closure) # 15
ブロックをProcオブジェクトに変換
ブロックをProcオブジェクトとして受けることができる。
def func2 hoge, &proc
hoge + proc.call
end
func2(100) do
200
end # 300
lambda
lambdaもprocを返すが、Proc.newとは異なる動きをする。
procの実行時にreturnするとprocの呼び出し元のスコープを抜けていた。
lambdaは実行時にreturnしてもlambdaの呼び出し元のスコープを抜けない。
下の例でlambdaが返したprocが途中で終わっても
callerはそこで抜けず、proc.callの後が実行される。
def caller
proc = lambda{ return 1 }
proc.call
2
end
lambdaの別の書き方
以下のように格好良く書ける。他の言語の同様の構文に似せた感じ。
lmd2 = ->(hoge,fuga) { hoge + fuga }
lmd2.call(100,200) # 300