跳到主要内容
信息
· 文章中可能会出现一些错误,希望大佬们可以在评论区指出;

08-模块与包

将所有代码都写进一个文件里会显得十分臃肿,因此需要将不同职能的代码分成各种模块(Module)写到不同的文件中,然后使用Lua语言提供的require()函数读取这些模块,让包(Package)管理这些模块。

导入模块​

可以通过require("模块文件名")来读取模块,该函数在初次加载模块时会执行对应模块代码一次,如果模块是用表实现的,可以在它返回表时用局部变量获取它:

local m = require("math")

require()函数的大致执行流程如下:

  1. 在表package.loaded中检查模块是否已经被加载,是的话就直接返回对应的值;
  2. 尝试在由package.path指定的路径中搜索模块,找到了就用loadfile()加载它;
  3. 如果找不到Lua文件,就尝试在由package.cpath指定的路径中搜索C语言模块,找到了就用package.loadlib()加载它;
  4. 加载模块成功后,将模块的返回值或true保存在表package.loaded中;

删除模块​

根据require()函数的执行流程,要想删除/重新加载指定的模块,需要删除存储在package.loaded中的模块返回值:

package.loaded["模块名"] = nil
package.loaded.模块名 = nil

编写模块​

模块通常用表实现,且内部没有全局变量。例如复数模块complex.lua的内容如下:

示例:复数模块 complex.lua点击展开/折叠代码
local M = {}

local function new(r, i)
return { r = r, i = i }
end

local function add(c1, c2)
return new(c1.r + c2.r, c1.i + c2.i)
end

local function sub(c1, c2)
return new(c1.r - c2.r, c1.i - c2.i)
end

local function mul(c1, c2)
return new(c1.r * c2.r - c1.i * c2.i, c1.r * c2.i + c1.i * c2.r)
end

local function inv(c)
local n = c.r ^ 2 + c.i ^ 2
if n == 0 then
error("division by zero complex number")
end
return new(c.r / n, -c.i / n)
end

local function div(c1, c2)
return mul(c1, inv(c2))
end

local function to_string(c)
return string.format("(%g, %g)", c.r, c.i)
end

M.new = new
M.i = new(0, 1)
M.add = add
M.sub = sub
M.mul = mul
M.div = div
M.to_string = to_string

return M

然后在另一个文件中使用require()引用即可:

local C = require("Modules.complex")

local a = C.new(1, 2)
local b = C.new(3, 4)

print(C.to_string(C.add(a, b))) -- > (4, 6)
print(C.to_string(C.mul(a, b))) -- > (-5, 10)
print(C.to_string(C.div(a, b))) -- > (0.44, 0.08)
print(C.to_string(C.mul(C.i, C.i))) -- > (-1, 0) -- 验证 i² = -1

参考资料​