【问题标题】:Lua create multiple closure instancesLua 创建多个闭包实例
【发布时间】:2012-06-14 00:48:59
【问题描述】:

我在一个文件中有一些 lua 代码。我想创建此代码的多个闭包实例,每个实例都有不同的 _ENV 上值。我可以使用luaL_loadfile 加载文件并设置第一个上值,使用不同的表进行 N 次,以创建 N 个实例。但这不会加载和编译文件N次吗?

我想要做的 lua 等价物如下,除了没有加载文件

func_list = {}

for i = 1, 10 do
    local new_env = {hello=i, print=print}
    func_list[i] = loadfile("Code.lua", "t", new_env)
end

for i = 1, 10 do
    func_list[i]()
end

------ Code.lua ------
print(hello*hello)

有没有更好的方法来做到这一点?

【问题讨论】:

    标签: lua closures lua-api lua-5.2


    【解决方案1】:

    当你在 Lua 中加载一个字符串/文件时,你得到的回报是一个调用函数来实际运行文件。 load 为您做的只是一些额外的处理来设置_ENV

    但是,没有什么能阻止您自己设置_ENV。你可以这样做:

    -- Code.lua --
    _ENV = ...
    print(hello * hello)
    

    然后,您可以只加载/编译文件一次,并使用多个实例:

    local code = loadfile("Code.lua")
    
    env_list = {}
    for i = 1, 10 do
        local new_env = {hello=i, print=print}
        code(new_env)
        env_list[i] = new_env
    end
    

    如果您不希望用户在每个文件中写入_ENV = ...,您可以改为将文件加载到字符串中,自己添加该行并使用load 编译源代码。但这不适用于已编译的文件。

    【讨论】:

    • 你的意思是 code(new_env);func_list[i] = new_env 在 for 循环中。
    • 另外,而不是将_ENV = ... 附加到代码中。 DeadMG 的建议也应该有效吗? IE。在执行块之前将第一个上值设置为 new_env
    • 感谢您的评论,我已解决。关于第二个问题 - 你可以使用 this implementation of setfenv for Lua 5.2 来获得你想要的。请注意,现在您只有一个闭包,它改变了它的环境,而不是多个闭包。
    • 这很好,因为我只对code.lua 中的函数感兴趣。每次调用code,都会创建不同的闭包并将其添加到我们创建的环境表中。因此,即使我们只有一个code 闭包,每个环境都会为code.lua 中的函数提供单独的闭包。如果我们将整个代码包装在code.lua 中的匿名函数中,然后返回它,我们可以创建多个闭包。所以code(new_env) 会给我们一个使用 new_env 作为 _ENV 的闭包。
    【解决方案2】:

    使用IO库将文件加载成字符串,然后调用loadstring就可以了。

    或者,只需获取一个块,然后在执行之前更改它的环境

    【讨论】:

    • 如果我使用loadstring,它每次都会编译代码,对吧?
    • @z33m:是的,但至少您不必执行 I/O。编译后无法复制 Lua 块。
    猜你喜欢
    • 2011-11-21
    • 1970-01-01
    • 1970-01-01
    • 2017-03-30
    • 2018-07-11
    • 2017-11-15
    • 2020-07-08
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多