You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Lua 5.1中局部变量作为Upvalue不符合预期的问题

Lua 5.1闭包Upvalue的行为差异解析

正常工作的闭包示例

请看以下Lua 5.1代码:

function foo ()
 function makeAdder (withWhat)
   return function (a)
     return a + withWhat
   end
 end -- makeAdder
 f1 = makeAdder (6)
 f2 = makeAdder (7)
end -- foo

foo ()
print (f1 (2))  --> 8
print (f2 (2))  --> 9

闭包f1和f2分别以6和7作为Upvalue,调用后输出8和9,符合预期。

不符合预期的闭包示例

再看这段代码:

function foo ()
 local withWhat
 function makeAdder ()
   return function (a)
     return a + withWhat
   end
 end -- makeAdder

 withWhat = 6
 f1 = makeAdder ()
 withWhat = 7
 f2 = makeAdder ()
end -- foo

foo ()
print (f1 (2))  --> 9
print (f2 (2))  --> 9

创建闭包时f1和f2本应分别以6和7作为Upvalue,但调用后均输出9,不符合预期。为何f1的Upvalue会变成7而非创建时的6?(使用Lua版本为5.1.5)

问题核心原因

Lua 5.1中闭包捕获的是Upvalue的引用,而非值的副本,这是导致两种示例行为差异的关键:

  • 在第二个示例里,withWhat是foo函数内唯一的局部变量,所有闭包共享同一个Upvalue的引用。当执行withWhat = 6后创建f1,f1只是持有对这个变量的引用;后续withWhat = 7修改了变量的值,f1捕获的引用指向的还是同一个变量。最终调用闭包时,读取的是变量的最新值7,所以f1(2)输出9。
  • 第一个示例中,makeAdder的参数withWhat是每次调用函数时生成的新局部变量,每次调用makeAdder都会创建独立的Upvalue。f1和f2分别持有不同的Upvalue引用,各自对应6和7,因此调用时输出符合预期的结果。

内容的提问来源于stack exchange,提问作者Nick Gammon

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.14 04:35:10