Lua中的函数可以在调用之间存储本地值吗?
我正在阅读“Lua中的编程”,我不理解这段代码中Lua中函数的行为:Lua中的函数可以在调用之间存储本地值吗?,lua,closures,Lua,Closures,我正在阅读“Lua中的编程”,我不理解这段代码中Lua中函数的行为: function newCounter () local i = 0 return function () -- anonymous function i = i + 1 return i end end c1 = newCounter() print(c1()) --> 1 print(c1()) --> 2 在我看来,每个调用c1()都应该返回1,因为i在newCounter
function newCounter ()
local i = 0
return function () -- anonymous function
i = i + 1
return i
end
end
c1 = newCounter()
print(c1()) --> 1
print(c1()) --> 2
在我看来,每个调用c1()
都应该返回1
,因为i
在newCounter()的开头被初始化为零。但它看起来像一条线
local i = 0
在调用c1()
时跳过。而newCounter()
的行为类似于对象,而不像函数。我对Scheme和C#略知一二,所以我熟悉一级函数。函数返回函数对我来说没问题,但是它如何在调用之间存储i
的值呢?这是“正常”函数和闭包之间的区别
对于匿名函数,i
不是局部变量,也不是全局变量。这叫做非局部变量。请注意,执行匿名函数时,i
超出范围:
print(c1()) --> 1
print(c1()) --> 2
这里的要点是,i
的值存储在匿名函数中。该函数和所有非局部变量一起构成一个闭包。您可以将i
视为一个全局变量,仅由C1
可见。此外,i
在newCounter()
中初始化,而不是在返回的增量匿名函数中。我添加了“i”在ZeroBrane Studio中观察并开始调试此函数,它显示在c1()的调用之间i=nil。怎么可能呢?@corundi
在函数newCounter
返回时超出范围。您可以认为返回的闭包有一个独立的i
实例化。尝试创建另一个闭包c2=newCounter()
并同时使用这两个闭包。在解释器/REPL中,您可以尝试返回debug.getupvalue(c1,1)
或甚至是debug.setupvalue(c1,1,-5)
来进行实验。(i
是闭包c1
的第一个向上值/非局部变量,因此1
作为索引。)c2=newCounter()
将具有不同的i
。(所以,我不会用“全球”这个词。)