lua闭包

来源:互联网 发布:mysql联表删除 编辑:程序博客网 时间:2024/05/20 07:19

转载自  http://www.2cto.com/kf/201503/382691.html

闭包的概念

在Lua中,闭包(closure)是由一个函数和该函数会访问到的非局部变量(或者是upvalue)组成的,其中非局部变量(non-local variable)是指不是在局部作用范围内定义的一个变量,但同时又不是一个全局变量,主要应用在嵌套函数和匿名函数里,因此若一个闭包没有会访问的非局部变量,那么它就是通常说的函数。也就是说,在Lua中,函数是闭包一种特殊情况。另外在Lua的C API中,所有关于Lua中的函数的核心API都是以closure(而非function)来命名的,也可视为这一观点的延续。在Lua中,函数是一种第一类型值(First-Class Value),它们具有特定的词法域(Lexical Scoping)。


function Create(n)
   local function foo1()
      print(n)
   end
   local function foo2()
      n = n + 10
   end
   returnfoo1,foo2
end
 
f1,f2 = Create(2015)
f1() -- 打印2015
 
f2()
f1() -- 打印2025
 
f2()
f1() -- 打印2035

注意上面的例子中,闭包f1和f2共享同一个upvalue了


闭包在创建之时其upvalue就已不在堆栈上的情况也有可能发生,这是因为内嵌函数能引用更外层外包函数的局部变量:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
function Test(n)
   local function foo()
      local function inner1()
         print(n)
      end
      local function inner2()
         n = n + 10
      end
      returninner1,inner2
   end
   returnfoo
end
t = Test(2015)
f1,f2 = t()
f1()        -- 打印2015
 
f2()
f1()        -- 打印2025
 
g1,g2 = t()
g1()        -- 打印2025
 
g2()
g1()        -- 打印2035
 
f1()        -- 打印2035
注意上面的执行的结果表明了闭包f1、f2、g1和g2都共有同一个upvalue,这是因为在创建inner1,inner2这两个闭包被创建时堆栈上根本未找到n的踪影,而是直接使用闭包foo的upvalue。t = Test(2015)之后,t这个闭包一定已把n妥善保存好了,之后f1、f2如果在当前堆栈上未找到n就会自动到他们的外包闭包的upvalue引用数组中去找,并把找到的引用值拷贝到自己的upvalue引用数组中。所以f1、f2、g1和g2引用的upvalue实际也是同一个变量,而刚才描述的搜索机制则确保了最后他们的upvalue引用都会指向同一个地方。


0 0