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
相关产品推荐
相关产品推荐

