让模块可以访问父脚本中的局部变量

更新:

参考 当文件中的闭包看不到局部变量时该怎么办? 的一些进一步阅读让我恍然大悟,知道了为什么我的代码不能工作。

在 Lua 中,local x 可以被同一作用域内的任何东西看到 - 在相同的函数、if/then 结构、for 循环、从该函数调用的其他函数等中,但 不是 其他模块,即使它们是从局部作用域中调用的模块。我还没有找到比“因为原因”更好的解释,但至少知道模块是“正常”作用域行为的一个例外,至少可以让我放心。

原始帖子:

(非常抱歉,如果这里已经有答案了;我已经搜索了几个小时,但找不到。)

我为我喜欢的音频软件(Reaper)编写了一个 GUI 库。在录制/播放期间可能会运行脚本,因此性能是一个很大的问题,我尽可能地保持一切是本地的。总的来说很容易,但是当涉及到在脚本中使用 GUI 库 + 元素类时,我遇到了一些问题。

主 GUI 模块:

-- Core.lua --

local function GUI_table()
  local GUI = {}

  -- GUI 元素模板
  GUI.Element = {}
  function GUI.Element:new(name)
    local elm = {}
    setmetatable(elm, self)
    self.__index = self
    return elm
  end

  ...添加一堆 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()
...等等...

我当前通过 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

可以运行良好,但对性能没有任何帮助:模块代码中的错误仍然追溯到模块(即“Class - Button.lua”中的第23行),这使我认为模块仍然在它们自己的作用域中,我的本地 GUI 实际上没有被触摸。

我还尝试让 Core.lua 直接返回 GUI 表格,这样主脚本就可以拥有 local GUI = loadfile("Core.lua")() 了,但是我遇到了使元素模块可以访问它的麻烦,如上所述。我知道,这是作用域。

因此,考虑到上述所有因素,是否有一种“正确”的方法来编写/结构模块,以便一切最终都在本地的 GUI 中?我觉得已死的 module(..., package.seeall) 功能可能已经解决了此问题......也许不是。

谢谢。

点赞
用户3574628
用户3574628

这是循环依赖的问题。我注意到 ElementButtonGUI 内部,但它们不依赖于 GUI 进行构建。将 Element 放在它自己的文件中将允许您将所有内容都变为本地。

-- Core.lua --

local GUI = {}

-- GUI元素的模板
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,
}

-- 类 - Button.lua --

Button = require('Element'):new()
function Button:draw()
end

return Button
2018-05-08 18:13:21