嗨,我想将我的 Lua 文件分成两个文件。一个保存我的函数,一个可以调用它们。我对此进行了大量研究,我发现的所有资源都没有非常深入地解释这个过程。他们通常说使用:
require "subsystem.lua"
Run Code Online (Sandbox Code Playgroud)
我把它放在一个新的 Lua 文件的顶部,该文件保存在同一目录中,并且无法访问任何内容。
是否有我需要修改的配置文件?它在哪里?
您需要做的是返回一个包含您要访问的字段的表,subsystem.lua
然后在主文件中分配和使用该表中的字段。沿着这些路线的东西:
-- subsystem.lua
local function doSomething()
-- do something useful here
end
local function doMore()
-- do something else useful
end
return { doSomething = doSomething, doMore = doMore }
-- main.lua
local subsystem = require "subsystem" -- don't add `.lua` to your `require` call
subsystem.doSomething()
subsystem.doMore()
Run Code Online (Sandbox Code Playgroud)
您可能需要查看模块教程以获取详细信息。
该require
函数在一系列位置查找模块。可以通过调整全局表中的字段来广泛定制确切的地点列表package
。
了解在查找模块时使用了多少位置和名称的最简单方法是查看require
失败时产生的错误消息。例如,在我的 PC 上,Lua 5.1 是这样说的:
C:\用户\罗斯> lua Lua 5.1.4 版权所有 (C) 1994-2008 Lua.org, PUC-Rio > 需要“xyzzy” 标准输入:1:找不到模块“xyzzy”: 没有字段 package.preload['xyzzy'] 没有文件 '.\xyzzy.lua' 没有文件 'C:\Program Files (x86)\Lua\5.1\lua\xyzzy.lua' 没有文件 'C:\Program Files (x86)\Lua\5.1\lua\xyzzy\init.lua' 没有文件 'C:\Program Files (x86)\Lua\5.1\xyzzy.lua' 没有文件 'C:\Program Files (x86)\Lua\5.1\xyzzy\init.lua' 没有文件 'C:\Program Files (x86)\Lua\5.1\lua\xyzzy.luac' 没有文件 '.\xyzzy.dll' 没有文件 '.\xyzzy51.dll' 没有文件 'C:\Program Files (x86)\Lua\5.1\xyzzy.dll' 没有文件 'C:\Program Files (x86)\Lua\5.1\xyzzy51.dll' 没有文件 'C:\Program Files (x86)\Lua\5.1\clibs\xyzzy.dll' 没有文件 'C:\Program Files (x86)\Lua\5.1\clibs\xyzzy51.dll' 没有文件 'C:\Program Files (x86)\Lua\5.1\loadall.dll' 没有文件 'C:\Program Files (x86)\Lua\5.1\clibs\loadall.dll' 堆栈回溯: [C]:在函数“要求”中 标准输入:1:在主块中 [C]: ? >
在内部查看后,它寻找的第一个“真实”位置xyzzy
在名为.\xyzzy.lua
. 然后它会在lua.exe
找到的文件夹中尝试多个文件夹和名称。最后,它寻找可能提供它的 DLL。它搜索.lua
文件的文件夹列表由 中的字符串值控制package.path
。(DLL 中的可比较列表是package.cpath
。)在该值中,require
将用?
模块名称替换每个,然后尝试读取文件。使用第一个成功的。
(这里的故事稍微复杂一些;您可以创建require
用于查看不同位置的“搜索器”,甚至可以更改内置搜索器的顺序,但这是一个高级主题。)
因此,只需将模块放在当前目录的 Lua 文件中就可以正常工作,并且package.path
在调用require
自己的模块之前进行调整可以涵盖您将遇到的大多数怪癖。
简单来说,模块就是可以存储在package.loaded
. require
一旦找到它,它将如何处理它,以便多次调用require
只会搜索一次并始终返回相同的值。
传统的答案是“某物”是一个表,通常主要由可以调用的函数填充,偶尔还有值。该math
模块是一个很好的例子:它提供了许多函数,比如sin
and cos
,以及有用的值math.pi
and math.huge
。
除了存储在表中之外,模块中的函数没有什么特别之处。像任何其他函数一样,它接受参数并返回零个或多个值。唯一真正的规则是模块不应更改或添加全局变量。
所以一个非常小的模块文件可以很简单:
return {
addtwo = function(a, b) return a+b end,
subtwo = function(x) return x-2 end,
}
Run Code Online (Sandbox Code Playgroud)
如果存储为example.lua
可以这样使用:
local example = require "example"
print(example.addtwo(2,2)) -- 4
print(example.subtwo(42)) -- 40
Run Code Online (Sandbox Code Playgroud)
在大多数实际情况下,将所有代码粘贴在单个表声明中是行不通的。它不能很好地扩展,并且很难清楚地表达共享状态的函数之间的关系。
-- simple modules
-- capture the name searched for by require
local NAME=...
-- table for our functions
local M = { }
-- A typical local function that is also published in the
-- module table.
local function addtwo(a,b) return a+b end
M.addtwo = addtwo
-- Shorthand form is less typing and doesn't use a local variable
function M.subtwo(x) return x-2 end
return M
Run Code Online (Sandbox Code Playgroud)
Lua 5.1 包含一个名为的标准函数,module()
旨在用于模块实现的顶部。从来不需要使用它,并且很快就形成了共识,认为它不像希望的那样有用。它已被弃用。
因此,我上面展示的简单骨架没有使用它,并且可以移植到 Lua 5.1 以来的所有版本。