【问题标题】:Functions in Lua could store local values between calls?Lua 中的函数可以在调用之间存储本地值吗?
【发布时间】:2015-04-30 18:33:39
【问题描述】:

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

local i = 0

c1() 的调用中被跳过。 newCounter() 表现得像对象而不是函数。对Scheme和C#有点了解,所以对一流的函数比较熟悉。函数返回函数对我来说没问题,但它如何在调用之间存储i 的值?

【问题讨论】:

    标签: lua closures


    【解决方案1】:

    这是“普通”函数和闭包之间的区别。

    对于匿名函数,i 不是局部变量,也不是全局变量。它被称为非局部变量。请注意,当您执行匿名函数时,i 超出范围:

    print(c1()) --> 1
    print(c1()) --> 2
    

    这里的重点是,i 的值存储在匿名函数中。该函数和所有非局部变量一起构成一个闭包。

    【讨论】:

    • 此外,i 是在 newCounter() 中初始化的,而不是在返回的增量匿名函数中。
    • 我将“i”添加为 watch 并开始在 ZeroBrane Studio 中调试此函数,它显示在 c1() 调用之间 i=nil。怎么可能?
    • @corund i 在函数 newCounter 返回时超出范围。您可以认为返回的闭包具有i 的独立实例化。尝试创建另一个闭包c2 = newCounter() 并使用两者。
    • 在解释器/REPL 中,您可以尝试return debug.getupvalue( c1, 1 ) 甚至例如debug.setupvalue( c1, 1, -5 ) 进行实验。 (i 是闭包c1 的第一个上值/非局部变量,因此1 作为索引。)
    【解决方案2】:

    您可以将i 视为只有C1 可见的全局变量。

    【讨论】:

    • c2 = newCounter() 会有不同的i。 (所以,我不会使用“全局”这个词。)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-01-31
    • 2011-10-13
    • 2021-05-03
    • 2017-12-14
    相关资源
    最近更新 更多