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

我正在阅读“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()的开头被初始化为零。但它看起来像一条线

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。怎么可能呢?@corund
i
在函数
newCounter
返回时超出范围。您可以认为返回的闭包有一个独立的
i
实例化。尝试创建另一个闭包
c2=newCounter()
并同时使用这两个闭包。在解释器/REPL中,您可以尝试
返回debug.getupvalue(c1,1)
或甚至是
debug.setupvalue(c1,1,-5)
来进行实验。(
i
是闭包
c1
的第一个向上值/非局部变量,因此
1
作为索引。)
c2=newCounter()
将具有不同的
i
。(所以,我不会用“全球”这个词。)