Procとlambdaを使ってクロージャを書く。
自分の中のクロージャの認識は「独立したローカル変数の操作」程度である
簡単なサンプルとしてはカウンティングがよくある
[1] pry(main)> def closure
[1] pry(main)* count = 0
[1] pry(main)* return lambda { return count+=1 }
[1] pry(main)* end
=> nil
[2] pry(main)> c = closure
=> #<Proc:0x007ff73aa7e750@(pry):3 (lambda)>
[3] pry(main)> c.call
=> 1
[4] pry(main)> c.call
=> 2
[5] pry(main)> count = 100
=> 100
[6] pry(main)> c.call
=> 3
だが、Procでも同様のことをやろうとするとおかしなことになる
[1] pry(main)> def closure
[1] pry(main)* count = 0
[1] pry(main)* return Proc.new { return count += 1 }
[1] pry(main)* end
=> nil
[2] pry(main)> c = closure
=> #<Proc:0x007fef9aa7bed0@(pry):3>
[3] pry(main)> c.call
LocalJumpError: unexpected return
from (pry):3:in `block in closure'
こんな感じで「LocalJumpError: unexpected return」が発生する。
これはlambdaとProcにおけるreturnの扱いに違いがある。
lambdaではclosureメソッド内でのreturnと同じ扱いになるのだが、
Procの場合はcallを行った位置でのreturnの扱いとなる。そのため
今回はトップレベルでのreturnを行ったと同じ扱いになったため、
「LocalJumpError: unexpected return」が発生してしまったのである。
Procでやる場合は
def closure
count = 0
return Proc.new { count += 1 }
end
c = closure
p c.call
p c.call
p c.call
-------------------------------------------------------------
1
2
3
--------------------------------------------------------------
こんな感じになるのか。Procとlambdaで大分挙動が違うから扱いには注意
しないと大変なことになりそう。
参考文献