Lua 和序列化闭包

标签 lua closures

我正在尝试序列化和反序列化 Lua 闭包

我的基本理解是下面的工厂应该生成闭包(并且 Lua 在函数和闭包之间没有太大区别——即没有类型“闭包”)

> function ffactory(x) return function() return x end end
> f1 = ffactory(5)
> print(f1())
5                        <-- so far so good
> s = string.dump(f1)
> f2 = load(s)
> print(f2())
table: 00000000002F7BA0  <-- expected the integer 5
> print(f2()==_ENV)
true                     <-- definitely didn't expect this!

我希望整数 5 被序列化 f1 .或者,如果 string.dump无法处理闭包,我预计会出现错误。

我得到了完全不同的(但更多的是我的预期)结果。它看起来像 f2确实是一个闭包,但是 string.dump 在它被序列化时没有尝试序列化 x 的值。

docs不要帮我太多。 (他们所说的“......具有新的值(value)”是什么意思?)
> function ffactory(x) return function() return x+1 end end
> f1 = ffactory(5)
> print(f1())
6                        <-- good
> s = string.dump(f1)
> f2 = load(s)
> print(f2())
stdin:1: attempt to perform arithmetic on upvalue 'x' (a table value)
stack traceback:
        stdin:1: in function 'f2'
        stdin:1: in main chunk
        [C]: in ?

最佳答案

你可以做这样的事情来保存/恢复这些上值(注意它不处理不同函数之间共享的上值):

local function capture(func)
  local vars = {}
  local i = 1
  while true do
    local name, value = debug.getupvalue(func, i)
    if not name then break end
    vars[i] = value
    i = i + 1
  end
  return vars
end

local function restore(func, vars)
  for i, value in ipairs(vars) do
    debug.setupvalue(func, i, value)
  end
end  

function ffactory(x) return function() return x end end
local f1 = ffactory(5)
local f2 = (loadstring or load)(string.dump(f1))
restore(f2, capture(f1)) --<-- this restored upvalues from f1 for f2

print(f1(), f2())

这适用于 Lua 5.1 和 Lua 5.2。

如果您更改 ffactory,请注意一个有趣的结果稍微(添加 ​​math.abs(0) ;任何以任何方式使用全局表的东西都可以):
function ffactory(x) return function() math.abs(0) return x end end

现在,如果您恢复 upvalues 会得到相同的结果,但是如果您不恢复 upvalues,则会在 Lua 5.2 下出现运行时错误:
lua.exe: upvalues.lua:19: attempt to index upvalue '_ENV' (a nil value)
stack traceback:
upvalues.lua:19: in function 'f2'
upvalues.lua:24: in main chunk
[C]: in ?

关于Lua 和序列化闭包,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14509814/

相关文章:

lua - 从函数返回表的内部

c++ - 你如何将 Lua 粘合到 C++ 代码上?

linux - Conky 文件中 pre_exec 命令的 Lua "replacement"是什么?

javascript - ES2015 (ES6) 类中类构造函数的闭包

常规 : Closures or Methods

c - 在从 C 调用的函数中迭代 Lua 中的表

floating-point - 将有符号的 IEEE 754 float 转换为十六进制表示

php - 如何调用分配给类变量的 PHP 闭包?

javascript - 在 javascript 闭包中使用 setInterval

rust - 如何从 `FnMut` 返回捕获的变量