Procとcallメソッド
以下では、get_closureメソッドにより、クロージャオブジェクトを生成している。
その際初期値を設定している。
クロージャオブジェクトのcallメソッドによりクロージャを実行する。
初期値を設定した変数initial_valueはクロージャのスコープなので、
クロージャの外からは一切存在を管理する必要がない。
1 2 3 4 5 6 |
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と異なる。
1 2 3 4 5 |
def caller proc = Proc.new{ return 1 } proc.call 2 end |
Procオブジェクトをブロックに変換
作っておいたクロージャオブジェクトをメソッド実行時にブロックとして使用することができる。
メソッドの引数として、&を付与してProcオブジェクトを渡す。
1 2 3 4 5 |
def func hoge hoge + yield end closure = Proc.new {5} func(10, &closure) # 15 |
ブロックをProcオブジェクトに変換
ブロックをProcオブジェクトとして受けることができる。
1 2 3 4 5 6 |
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の後が実行される。
1 2 3 4 5 |
def caller proc = lambda{ return 1 } proc.call 2 end |
lambdaの別の書き方
以下のように格好良く書ける。他の言語の同様の構文に似せた感じ。
1 2 |
lmd2 = ->(hoge,fuga) { hoge + fuga } lmd2.call(100,200) # 300 |