闭包(closure)中的非局部变量

PIL中说道,一个closure就是一个函数加上改函数所需访问的所有“非局部的变量”。当中这个非局部的变量,可以是嵌套函数的外部函数中的变量,或者是一个包含着这个嵌套函数的 块,就是说closure闭包,包含了一系列理应超出了作用范围的变量,并可以使用这些变量。

看下面一些例子,是我根据对闭包的理解作出的几个实验的代码:

第一个是书本上的例子

function counter()
local i = 0
return function()
i = i + 1
 return i end
end

c1 = counter()
c2 = counter()
--这里c1c2接受的是函数的调用,而不是函数这个first-class value

print(c1()) -->1 print(c1()) -->2 print(c2()) -->1

local i 对于接受嵌套的函数(或者说闭包)的c1和c2,都有一个变量i在闭包里,他们i的值相互独立

 

第二个实验代码

上面代码中间的注释提及到

--"--这里c1c2接受的是函数的调用,而不是函数这个first-class value“

其实c1c2闭包相当于两个块

do
local i = 0
c1 = function()  --相当于第一个实验的 c1 = counter()
i = i+1
return i
end
end

do
local i = 0
c2 = function()  --c2 = counter()
i = i+1
return i
end
end

print(c1()) -->1
print(c1()) -->2
print(c2()) -->1

这样,对于 “闭包” 还有闭包中的 “非局部变量” 的理解就清晰多了。

 

BTW,可能在用闭包的时候会遇到一种错误

例如,非局部变量local i,漏了local,使i成为了全局变量,这样,上面的c1、c2两个闭包就共用同一个非局部的变量i了,果然是这样的。

测试一下:

function counter()
  i = 0     --全局的i,而不是local
 return function()
 i = i + 1
  return i end
 end

c1 = counter()
c2 = counter()

print(c1()) -->1
print(c1()) -->2
print(c2()) -->3

  

好了,接下来进一步测试,既然在变量i身上可能出现写少了local的错误,出现和预想的不一致,那么,对于first-class的函数来说,也同样存在一样的错误,

只要把函数的创建写成

local call =function()
  i = i + 1
  return i end
 --结果同上 -->1 2 3

 测试代码:

function counter()
local  i = 0
call =function() --call并不是局部的
 i = i + 1
  return i end
return call
 end

c1 = counter()
c2 = counter()

print(c1()) -->1
print(c2()) -->1
print(call()) -->2  --调用call()后结果是2,那么这个"2"是c1还是c2的"1"递增得到的呢?
print(c1()) -->2 --递增前是1
print(c2()) -->3 --递增前是2,call()递增了c2闭包中的非局部变量i

  这样的话,要知道一下,call()调用的是最后赋值的闭包c2。

thats it.

 

 

posted @ 2012-09-10 22:40  KelvinDesus  阅读(380)  评论(0编辑  收藏  举报