クロージャの動作

Ruby の lambda はクロージャです。クロージャの動作は、初心者にはなかなかむずかしい。ちなみに蛇足ですが、lambda {|a, b| ..}->(a, b) {..} とは同じことです。

def a(fn)
  b = 100
  fn[5]
  p b.object_id    #=>201
end

b = 1
p b.object_id    #=>3
f = ->(i) {p (b + i).to_s}
f[2]    #=>"3"
a(f)    #=>"6"
b = 40
f[10]   #=>"50"
a(f)    #=>"45"
p b.object_id    #=>81

不思議な感じだな。lambda 内の b は、オブジェクトid ではなく、スコープに依存しているのか。

なお、次はエラーになります。

f = ->(i) {p (b + i).to_s}    #=>undefined local variable or method `b' for main:Object (NameError)
b = 10
p f[15]

しかし、次はエラーにならない。

b = 0
f = ->(i) {p (b + i).to_s}
b = 10
f[15]    #=>"25"

なかなかむずかしいな。