Lua: 创建模块系统

我想创建一个具有不同文件夹中几个模块的程序。主程序将确定需要加载哪个模块并加载它。此外,它还将加载一些核心功能。

我创建了这种逻辑的原型,它工作得很好。但是由于我是 Lua 的新手,我不确定实现这种逻辑的正确方式。

目前,我的文件结构如下所示:

enter image description here

aoc(主程序):

aoc = {}
aoc_base_path = debug.getinfo(1).source:match("@(.*)/.*$") -- 基本路径到我的程序
if not aoc_base_path then
  aoc_base_path = ''
else
  aoc_base_path = aoc_base_path..'/'
end

local aoc_base_arg={...}
dofile(aoc_base_path.."core/core")

local module = assert(loadfile(aoc_base_path.."modules/"..aoc_base_arg[1].."/module"))
local arg = table.copy(aoc_base_arg) -- 这是我的自定义函数(我不提供列表,它只是复制一个表到另一个表)
table.remove(arg,1)
module(arg,aoc) -- 将除第一项之外的所有参数传递给模块

core/core(核心函数加载器):

dofile (aoc_base_path..'core/move')

core/move

local function move(direction, refuel, dig, attack)
  -- 一些本地函数中的逻辑(不被模块覆盖)
end

function aoc.move()
  -- 全局函数(如果需要,模块的逻辑可以更改)
  return move()
end

modules/mine/module(模块):

local arg={...} -- 我在 aoc 主程序中传递了2个参数
arg = arg[1]
local aoc = arg[2]
aoc.move()

现在

lua> aoc mine

lua> path/to/aoc mine

都可以正常工作。但是,有人能指出我是否做错了什么吗?

编辑: 更改获取aoc_base_path的逻辑

点赞
用户1847592
用户1847592

你可以简化 aoc

aoc = {}
aoc_base_path = debug.getinfo(1).source:match("@(.*/)") or ''

dofile(aoc_base_path.."core/core")

local module = assert(loadfile(aoc_base_path.."modules/".. ... .."/module"))
module({select(2,...)},aoc)

你可以将 aoc 简化为以下步骤:

aoc = {}
dofile("core/core")
local module = assert(loadfile("modules/".. ... .."/module"))
module({select(2,...)},aoc)
2013-04-12 09:32:51
用户936986
用户936986

可以使用 Lua 的内置模块功能和 require 来实现。通过适当设置 package.loaders,可以将标准系统配置为从任何位置和以任何方式加载模块。具体说,可以从特定目录、直接从 HTTP,或根据 RFC 1149 由鸽子传递 - 它都能做到。

2013-04-12 12:18:07
用户2221331
用户2221331

为了保持你的目录结构基本相同,但利用lua包系统,你可以采用以下方法:

在你的基本路径中,有一个名为aoc.lua的文件:

local aoc = {}

local module = ...
local dir = module:gsub("%.","%/"):sub(1,-4)

package.path = dir.."?.lua;"..package.path
package.path = dir.."?/init.lua;"..package.path
package.path = dir.."modules/?.lua;"..package.path

return aoc

在/core中有一个名为init.lua的文件,require需要包含的核心包

require"core.move"

然后你的核心包会像这样:

local function move(direction, refuel, dig, attack)
  -- some logic in local function (to not be overwriten in module)
end

require"aoc".move = move

在/modules中,你可以更简单地为每个模块创建一个lua文件,因此/modules/mine.lua看起来像:

local aoc = require"aoc"

aoc.move()

然后,在lua提示符下,你会写:

lua> require"path.to.aoc"

lua> require"core" -- load up the core modules

lua> require"mine" -- load mine

##编辑

如果您想保持完全相同的风格,请将aoc.lua更改为只是return {},并添加一个名为aoc的文件,如下所示:

local dir = debug.getinfo(1).source:match("@(.*)/.*$") -- base path to my program
if not dir then dir = ''
else dir = dir..'/'
end

package.path = dir.."?.lua;"..package.path
package.path = dir.."?/init.lua;"..package.path
package.path = dir.."modules/?.lua;"..package.path

require"core"
for _,mod in ipairs{...} do
    require(mod)
end

我建议这种方法的优点是,所有的混乱都在一个文件中,即aoc,在这种情况下,其余的文件结构使用相当标准的lua包约定。

2013-04-12 13:09:44