gpt4 book ai didi

lua - 在不影响全局命名空间的情况下创建相互依赖的 Lua 文件套件

转载 作者:行者123 更新时间:2023-12-04 17:23:44 31 4
gpt4 key购买 nike

tl;博士 : 什么设计模式允许你将 Lua 代码拆分到需要共享一些信息而不影响全局表的多个文件上?

背景

在 Lua 中创建库会影响全局命名空间,这种做法被认为是不好的形式:

--> somelib.lua <--
SomeLib = { ... }

--> usercode.lua <--
require 'somelib'
print(SomeLib) -- global key created == bad

相反,最好的做法是创建一个使用局部变量的库,然后将它们返回给用户以在他们认为合适的时候进行分配:

--> somelib.lua <--
local SomeLib = { ... }
return SomeLib

--> usercode.lua <--
local theLib = require 'somelib' -- consumers name lib as they wish == good

使用单个文件时,上述模式可以正常工作。但是,当您有多个相互引用的文件时,这变得相当困难。

具体例子

您如何重写以下文件套件以使断言全部通过?理想情况下,重写将在磁盘上保留相同的文件以及每个文件的职责。 (通过将所有代码合并到一个文件中进行重写是有效的,但没有帮助;)

--> test_usage.lua <--
require 'master'

assert(MASTER.Simple)
assert(MASTER.simple)
assert(MASTER.Shared)
assert(MASTER.Shared.go1)
assert(MASTER.Shared.go2)
assert(MASTER.Simple.ref1()==MASTER.Multi1)
assert(pcall(MASTER.Simple.ref2))
assert(_G.MASTER == nil) -- Does not currently pass

--> master.lua <--
MASTER = {}
require 'simple'
require 'multi'
require 'shared1'
require 'shared2'
require 'shared3'
require 'reference'

--> simple.lua <--
MASTER.Simple = {}
function MASTER:simple() end

--> multi.lua <--
MASTER.Multi1 = {}
MASTER.Multi2 = {}

--> shared1.lua <--
MASTER.Shared = {}

--> shared2.lua <--
function MASTER.Shared:go1() end

--> shared3.lua <--
function MASTER.Shared:go2() end

--> reference.lua <--
function MASTER.Simple:ref1() return MASTER.Multi1 end
function MASTER.Simple:ref2() MASTER:simple() end

失败:设置环境

我想通过使用自我引用将环境设置到我的主表来解决问题。这在调用像 require 这样的函数时不起作用但是,当他们改变环境时:

--> master.lua <--
foo = "original"
local MASTER = setmetatable({foo="captured"},{__index=_G})
MASTER.MASTER = MASTER
setfenv(1,MASTER)
require 'simple'

--> simple.lua <--
print(foo) --> "original"
MASTER.Simple = {} --> attempt to index global 'MASTER' (a nil value)

最佳答案

您赋予 master.lua 两项职责:

  • 它定义了公共(public)模块表
  • 它导入所有子模块

  • 相反,您应该为 (1) 创建一个单独的模块并将其导入所有子模块:
    --> common.lua <--
    return {}

    --> master.lua <--
    require 'simple'
    require 'multi'
    require 'shared1'
    require 'shared2'
    require 'shared3'
    require 'reference'
    return require'common' -- return the common table

    --> simple.lua <--
    local MASTER = require'common' -- import the common table
    MASTER.Simple = {}
    function MASTER:simple() end

    等等

    最后把 test_usage.lua的第一行改一下使用局部变量:
    --> test_usage.lua <--
    local MASTER = require'master'
    ...

    测试现在应该通过了。

    关于lua - 在不影响全局命名空间的情况下创建相互依赖的 Lua 文件套件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14942472/

    31 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com