闭包(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.