【问题标题】:Letting modules access a Local in the parent script让模块访问父脚本中的 Local
【发布时间】:2018-10-18 13:33:14
【问题描述】:

更新:

一些进一步的阅读(local variable cannot be seen in a closure across the file?)给了我一个“啊哈!”关于我的代码不起作用的确切原因。

在 Lua 中,local x 对同一作用域内的任何事物都是可见的——同一函数中的事物、if/then 结构、for 循环、从该函数调用的其他函数等,但 不是其他模块,即使它们是从本地范围内调用的。我没有找到比“因为原因”更好的解释,但只要知道模块是“正常”范围行为的例外,至少让我放心。

原帖:

(非常抱歉,如果那里有这个问题的答案;我已经在谷歌上搜索了几个小时,结果很短。)

我为我喜欢的音频软件 (Reaper) 编写了一个 GUI 库。在录制/播放期间运行脚本的潜力很大,因此性能是一个大问题,我正在尝试尽可能将所有内容保持在本地。总的来说很简单,但是在脚本中使用 GUI 库 + 元素类时我遇到了一些麻烦。

主 GUI 模块:

-- Core.lua --

local function GUI_table()
  local GUI = {}

  -- Template for GUI elements
  GUI.Element = {}
  function GUI.Element:new(name)
    local elm = {}
    setmetatable(elm, self)
    self.__index = self
    return elm
  end

  ...add a bunch of GUI.do_this = function()....

  return GUI

  end
GUI = GUI_table()

所有的 GUI 元素都是相同格式的独立文件:

-- Class - Button.lua --

if not GUI then throw_a_missing_library_error_and_quit end

GUI.Button = GUI.Element:new()
function GUI.Button:draw()
...etc...

我目前正在通过loadfile("Core.lua")() 从父脚本加载它们。这工作得很好,但它会将 GUI 放在全局表中,并带有相关的查找开销。尝试重写一些东西以使 GUI 可以是本地的,到目前为止,进展并不顺利。我试过了:

local GUI
loadfile("Core.lua")()
loadfile("Class - Button.lua")()
...

失败,因为主脚本的 GUI 调用都转到本地 _GUI,但加载的文件由于作用域而无法查看或添加。

loadfile("Core.lua")()
loadfile("Class - Button.lua")()
local GUI = GUI

运行良好,但在性能方面并没有什么不同:模块代码中的错误仍然可以追溯到模块(即“类中的第 23 行 - Button.lua”),这导致我假设模块仍然包含在他们自己的范围和我的本地 GUI 实际上并没有被触及。

我也试过让 Core.lua 直接返回 GUI 表,所以主脚本可以有local GUI = loadfile("Core.lua")(),但我在给出元素时遇到了麻烦模块访问它,如上所述。我知道,范围界定。

那么,鉴于以上所有情况,是否有一种“正确”的方式来编写/构建模块,以便所有内容都在本地 GUI 中结束?我的印象是,已经失效的 module(..., package.seeall) 功能可以解决这个问题……也许不会。

干杯。

【问题讨论】:

    标签: lua scoping


    【解决方案1】:

    这是循环依赖的问题。我注意到 ElementButton 进入 inside GUI,但它们的构造并不依赖 GUI。将Element 放在它自己的文件中将允许您将所有内容都本地化。

    -- Core.lua --
    
    local GUI = {}
    
    -- Template for GUI elements
    GUI.Element = require 'Element'
    
    GUI.Button = require 'Button'
    
    return GUI
    
    -- Element.lua --
    
    return {
      new = function(self, name)
        local elm = {}
        setmetatable(elm, self)
        self.__index = self
        return elm
      end,
    }
    
    -- Class - Button.lua --
    
    Button = require('Element'):new()
    function Button:draw()
    end
    
    return Button
    

    【讨论】:

    • 感谢您的回答,就我的帖子中给出的细节而言,这非常有意义。在我为简洁起见而省略的代码中,实际上有很多对 GUI.__ 的调用 - Core.lua 处理用户输入、重绘元素,然后提供实用函数Lua 和我正在使用的 API 没有。 (我知道,糟糕的代码气味。我所询问的范围问题也导致我将它们放在一起)。所有元素类都广泛使用 Core 的功能 - 我很高兴编辑 OP,或在此处提供更多代码 - 不确定 StackOverflow 认为什么是“礼貌”。谢谢。
    • UI 内容可能是高级别的,需要(可能是间接的)访问其他所有内容。实用功能可能是其他一切都依赖的低级东西。通过将实用程序函数提取到它们自己的文件中,您应该能够取得重大进展。如果这还没有完成工作,请继续寻找可以移动到他们自己的文件中的内容,直到没有更多的循环依赖项为止。至于编辑您的问题,听起来您的实际代码只是您已经发布的内容的更复杂的版本。我不知道这是否会改变我的答案。
    猜你喜欢
    • 2021-03-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-10-25
    • 2018-06-14
    相关资源
    最近更新 更多