lua5.1 模块理解
http://www.lua.org/manual/5.1/manual.html#pdf-module
模块
5.3 – Modules
The package library provides basic facilities for loading and building modules in Lua. It exports two of its functions directly in the global environment: require
and module
. Everything else is exported in a table package
.
package库提供了基本的功能,可以实现加载和构建模块。
此库开放了两个接口在全局环境中(_G) require module ,
除了这两个接口,其他所有功能都开放到package表中。
实际上 require 文件 的结果 都存储在 package.loaded 表中。 例如 require “xxx”, 结果是 package.loaded[“xxx”] = yyy (yyy 是 xxx.lua 执行结果的返回值)。
require
require (modname)
Loads the given module. The function starts by looking into the package.loaded
table to determine whether modname
is already loaded. If it is, then require
returns the value stored at package.loaded[modname]
. Otherwise, it tries to find a loader for the module.
require 语句, 会先查询 package.loaded 表, 如果表中存在, 则将 package.loaded[modname]的值作为 require 的返回值。 否则, 尝试查询模块的 loader。
To find a loader, require
is guided by the package.loaders
array. By changing this array, we can change how require
looks for a module. The following explanation is based on the default configuration for package.loaders
.
查询 loaders, 需要按照 package.loaders数组顺序查询loader。
First require
queries package.preload[modname]
. If it has a value, this value (which should be a function) is the loader. Otherwise require
searches for a Lua loader using the path stored in package.path
. If that also fails, it searches for a C loader using the path stored in package.cpath
. If that also fails, it tries an all-in-one loader (see package.loaders
).
首先 require 查询 package.preload表,如果失败,
然后使用 package.path存储的路径查找 lua loader, 如果失败,
然后使用package.cpath春初的路径查找 c loader, 如果失败,
则尝试 all-in-one loader。
Once a loader is found, require
calls the loader with a single argument, modname
. If the loader returns any value, require
assigns the returned value to package.loaded[modname]
. If the loader returns no value and has not assigned any value to package.loaded[modname]
, then require
assigns true to this entry. In any case, require
returns the final value of package.loaded[modname]
.
如果loader找到, 则 调用 此loader, 入参为一个字符串 modname。
loader(modname)
如果loader调用有返回任何值, 则设置这个返回值到 package.loaded[modname]中。
如果 loader调用没有返回值, 或者没有设置package.loaded[modname], 则 require 设置true给
package.loaded[modname]。
理解: 对于lua文件, 对应的一个loader, 此loader是一个函数, 函数的环境为 require执行的环境,
lua:
local a = 111
print(a)
return a
loader:
function xx_loader( modname )
local a = 111
print(a)
return a
end
If there is any error loading or running the module, or if it cannot find any loader for the module, then require
signals an error.
module
module (name [, ···])
Creates a module. If there is a table in package.loaded[name]
, this table is the module. Otherwise, if there is a global table t
with the given name, this table is the module. Otherwise creates a new table t
and sets it as the value of the global name
and the value of package.loaded[name]
. This function also initializes t._NAME
with the given name, t._M
with the module (t
itself), and t._PACKAGE
with the package name (the full module name minus last component; see below). Finally, module
sets t
as the new environment of the current function and the new value of package.loaded[name]
, so that require
returns t
.
http://www.cnblogs.com/orez88/articles/2139160.html
- module
当在模块文件中使用module函数的时候,如下所示;
- module “mymodule”
实际上等同于以下的语句:
- local modname = “mymodule” – 定义模块名
- local M = {} -- 定义用于返回的模块表
- _G[modname] = M -- 将模块表加入到全局变量中
- package.loaded[modname] = M -- 将模块表加入到package.loaded中,防止多次加载
- setfenv(1,M) -- 将模块表设置为函数的环境表,这使得模块中的所有操作是以在模块表中的,这样定义函数就直接定义在模块表中
通过module(),可以方便的编写模块中的内容。
If name
is a compound name (that is, one with components separated by dots), module
creates (or reuses, if they already exist) tables for each component. For instance, if name
is a.b.c
, then module
stores the module table in field c
of field b
of global a
.
将 路径层级 和 命名空间层级 完美契合:
module 文件 存储在 test/newModule.lua文件中
module(..., package.seeall)
dingzhiprint = function ()
print("nasView print ----22 55")
end
调用文件, 为 test.lua, 其使用方法 与路径一致。
require("test.newModule")
test.newModule.dingzhiprint()
This function can receive optional options after the module name, where each option is a function to be applied over the module.
lua5.2 module 不建议使用原因
1、 module 的接口 增加了开发者理解难度:
需要在 module 声明前, 将需要使用的 变量 local 声明, 不能直接使用全局变量。 虽然可以应用 package.seeall 可以解决这个问题, 还是不够直接。
- local modname = “mymodule” – 定义模块名
- local M = {} -- 定义用于返回的模块表
- _G[modname] = M -- 将模块表加入到全局变量中
- package.loaded[modname] = M -- 将模块表加入到package.loaded中,防止多次加载
- setfenv(1,M) -- 将模块表设置为函数的环境表,这使得模块中的所有操作是以在模块表中的,这样定义函数就直接定义在模块表中
2、 module语法破坏了全局环境, 可能导致命名冲突。
module(…)用法不会导致冲突, 但是如果用户自定义 modname, 则若干模块很容易冲突,
例如 a b 两个文件夹, a/a.lua 定义了 module(“test”) b/b.lua 也定义了 module(“test”),
则造成冲突。
https://john.nachtimwald.com/2014/07/19/writing-lua-modules/
lua 5.2 推荐使用方法:
local
M = {}
function
M.func1()
(
"func1"
)
end
function
M.func2()
(
"func2"
)
end
return
M
local
fm = require(
"functions_module"
)
fm.func1()
fm.func2()