关于lua的闭包(Closure)和Upvalue

Lua闭包与Upvalue详解
本文详细介绍了Lua语言中的闭包(Closure)和Upvalue的概念,并通过具体示例展示了如何利用Lua API创建闭包及操作Upvalue,帮助读者深入理解Lua的高级特性。

关于lua的闭包(Closure)和Upvalue

upvalue:嵌套函数的外部函数的局部变量
function func(a) <== 这个函数返回值是一个函数
return function ()
    a = a + 1    <== 这里可以访问外部函数func的局部变量a,这个变量a就是upvalue
    return a 
end
end

func返回一个匿名函数,可用变量接取之。该匿名函数有一个upvalue a(有点像C函数的static变量),初值为首次调用func时的参数

闭包:一个匿名函数加上其可访问的upvalue
c = func(1) <== c现在指向一个拥有upvalue a = 1的匿名函数,c也被称作一个闭包
c()          <== 返回2
c()          <== 返回3
c2 = func(1) <== c2现在指向另外一个拥有upvalue a = 1的匿名函数,c2也被称作一个闭包
c2()         <== 返回2

下面是示例代码:

int 
generatecclosure(lua_State *L)        /* 闭包产生器 */
{
    lua_pushnumber(L, 0);             /* 压入第一个upvalue */ 
    lua_pushnumber(L, 0);             /* 压入第二个upvalue */
    lua_pushcclosure(L, cclosure, 2); /* 压入闭包的同时也把upvalue置入该闭包的upvalue表 */
    return 1;                         /* 返回闭包 */
}

int 
cclosure(lua_State *L)
{
    double upval1, upval2;
    upval1 = lua_tonumber(L, lua_upvalueindex(1)); /* 注意upvalue索引1,2是闭包依赖的,不会和其他的闭包中的索引冲突 */
    upval2 = lua_tonumber(L, lua_upvalueindex(2));
    upval1++; upval2++;    
    lua_pushnumber(L, upval1); lua_replace(L, lua_upvalueindex(1));/* 更新upvalue1 */
    lua_pushnumber(L, upval2); lua_replace(L, lua_upvalueindex(2));/* 更新upvalue2 */
    lua_pushnumber(L, upval1 + upval2);
    return 1;
}

int 
generatecclosure2(lua_State *L)        
{
    lua_pushnumber(L, 10);             
    lua_pushnumber(L, 10);             
    lua_pushcclosure(L, cclosure2, 2); 
    return 1;                          
}

int 
cclosure2(lua_State *L)
{
    double upval1, upval2;
    upval1 = lua_tonumber(L, lua_upvalueindex(1));
    upval2 = lua_tonumber(L, lua_upvalueindex(2));
    upval1++; upval2++;
    lua_pushnumber(L, upval1); lua_replace(L, lua_upvalueindex(1));
    lua_pushnumber(L, upval2); lua_replace(L, lua_upvalueindex(2));
    lua_pushnumber(L, upval1 + upval2);
    return 1;
}

然后向lua虚拟机注册一下全局函数:

lua_register(L, "generatecclosure", generatecclosure);
lua_register(L, "generatecclosure2", generatecclosure2);

最后执行main.lua:

c = generatecclosure()
c2 = generatecclosure2()
print(c()) -- 2
print(c()) -- 4
print(c2()) -- 22
print(c2()) -- 24

<think> 我们之前讨论了元表元方法,现在用户转向闭包closure)的概念。根据用户问题:“我想了解Lua闭包closure)的定义”。我们需要给出闭包的明确定义,并解释其在Lua中的工作机制特点。 闭包Closure)在Lua中是指一个函数以及它所访问的非局部变量(upvalue)的组合。在Lua中,函数是第一类值,可以嵌套定义,内部函数可以访问外部函数的局部变量,这些被内部函数访问的外部局部变量称为上值(upvalue)。当外部函数执行结束后,这些局部变量并不会立即消失,因为内部函数(闭包)还在引用它们,所以它们的生命周期被延长了。 定义要点: 1. 闭包是一个函数,它可以访问并记住其创建时的词法作用域中的变量。 2. 即使外部函数已经执行完毕,闭包仍然可以访问那些变量(即upvalue)。 3. 多个闭包可以共享同一个upvalue,从而通过这个upvalue进行通信。 示例: ```lua function outer() local count = 0 -- 这个局部变量将成为闭包upvalue return function() -- 返回一个闭包(匿名函数) count = count + 1 return count end end local counter1 = outer() -- 创建闭包counter1 print(counter1()) --> 1 print(counter1()) --> 2 local counter2 = outer() -- 创建另一个闭包counter2,有独立的upvalue print(counter2()) --> 1 -- counter2的count是独立的 ``` 在这个例子中: - `outer`函数内部定义了一个局部变量`count`一个匿名函数(闭包)。 - 匿名函数引用了`count`,因此`count`成为该闭包的一个upvalue。 - 每次调用`outer`都会创建一个新的`count`新的闭包,所以`counter1``counter2`各自拥有独立的`count`。 闭包Lua中非常常见,常用于: - 迭代器(保存迭代状态) - 回调函数(保留上下文) - 创建具有私有状态的函数(类似于面向对象中的私有变量) 注意:由于闭包会延长其引用的upvalue的生命周期,因此不当使用可能导致内存泄漏。 引用:根据Lua官方文档,闭包Lua实现词法作用域的核心机制[^1]。 相关问题: 1. Lua闭包
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值