Searchers
In reality, require is a little more complex than we have described. The search
for a Lua file and the search for a C library are just two instances of a more
general concept of searchers. A searcher is simply a function that receives the
module name and returns either a loader for that module or nil if it cannot find
one.
> =package.searchpath("lession14",package.path);
C:\Trevor\lua\bin\lession14.lua
> =f
function: 0036C558
The array package.searchers lists the searchers(searcher 其实就是个函数而已,这么说我们也可以定义自己的searcher,and put into the package.searchers table) that require uses. When
looking for a module, require calls each searcher in the list passing the module
name, until one of them finds a loader for the module. If the list ends without a
positive response, require raises an error.
> for k,v in pairs(package.searchers) do print (k,v); end
1 function: 018F1330
2 function: 018F1350
3 function: 018F1370
4 function: 018F1390
也就是require 接受到moduleName 参数后其实会依次调用 package.searchers 里面的函数,知道有一个返回loader
1 =package.searchers[1]("lession14")
no field package.preload['lession14'] -- the first searcher is the preload
回顾上面的内容 :The first step of require is to check in tablepackage.loaded whether the module is already
loaded.
2=package.searchers[2]("lession14")--the second searcher
function: 00369498 C:\Trevor\lua\bin\lession14.lua --here the second searcher return a loader, a loader is just a
function.
3=package.searchers[3]("lession14") --the
no file 'C:\Trevor\lua\bin\lession14.dll'
no file 'C:\Trevor\lua\bin\loadall.dll'
no file '.\lession14.dll'
The preload searcher allows the definition of an arbitrary function to load a
module. It uses a table, called package.preload, to map module names to loader
functions. When searching for a module name, this searcher simply looks for the
given name in the table. If it finds a function there, it returns this function as
the module loader. Otherwise, it returns nil. This searcher provides a generic
method to handle some non-conventional situations. For instance, a C library
statically linked to Lua can register its luaopen_ function into the preload table,
so that it will be called only when (and if) the user requires that module. In this
way, the program does not waste time opening the module if it is not used.
也就是我会有些preload 的module ,可以注册到这个table上,当Lua 运行时并不会真正load,而是require 的时候才会真正
load ,当load 完后,会填入package.loaded .
mysearcher=function(moudleName) return loadfile(package.path.mypath..moduleName..".lua") end;
rawset(package.searcher,5,mysearcher);
这个是我自己定义的searcher ,由于 Lua 的package.searchers metable __newindex不允许我update 第五个 element, so i choose rawset
回顾上面的内容,我们来猜测:
first we know package.loaded, pakcage.path, package.cpath. package.searchpath, package.searchers.
require("X"), check package.loaded not found.
package.searchers each searcher function will callpackage.searchpath, package.searchpath, will get package.path
and pacakge.cpath. when find the file, call loadfile /package.loadlib. when return the loader update the package.loaded.
1.first approach
===complex.lua
local M = {}
function M.new (r, i)
function M.sub (c1, c2)
return M.new(c1.r - c2.r, c1.i - c2.i)
end
function M.mul (c1, c2)
return M.new(c1.r*c2.r - c1.i*c2.i, c1.r*c2.i + c1.i*c2.r)
end
local function inv (c) --define as local will become a private function
return M =======at last return this table as a module.
mylib=require("complex");
============
2.second approach.
local function a,b,c,d.....
return {
new=a,
k=b,
fn1=c,
,,,,,
} --第二办法是在最后才return the table, then in the function definition ,we no need the prefix M.
3. third approach
local M = {}
package.loaded[...] = M -- ... 可变参数,其实就是require (para) ,para module 的名称了
print(...) --ie : require("myDefinemodel") , will print : myDefinemodel
......
function M.sub (c1, c2)
return M.new(c1.r - c2.r, c1.i - c2.i)
end
other funciton like M.funName....
but no need to return the table.
15.3 Using Environments
One drawback of those basic methods for creating modules is that it is all too
easy to pollute the global space, for instance by forgetting a local in a private
declaration, we can use _ENV
local M = {}
_ENV = M
a=100; -->M.a ,
function add (c1, c2) --不在需要 M.add, so this style will be final way to write a module
return new(c1.r + c2.r, c1.i + c2.i)
end
--After that, when we declare function add, it goes to M.add:
return M;
What is missing, of course, is access to other modules. Once we change the
value of _ENV, we lose access to all previous global variables. There are several
ways to recover this access, each with its pros and cons.
One solution is inheritance:
local M = {}
setmetatable(M, {__index = _G})
_ENV = M
---- second
local M = {}
local _G = _G
_ENV = M -- or _ENV = nil -- whey _ENV =nil also work, because, M declare as local
Now you must prefix any global name with _G., but the access is a little faster,
because there is no metamethod involved.
15.4 Submodules and Packages
Lua allows module names to be hierarchical, using a dot to separate name levels.
For instance, a module named mod.sub is a submodule of mod. A package is a
complete tree of modules; it is the unit of distribution in Lua.
---/modLivedirector/mod.lua
<function List here>
return table
--<modLivedirector>/mod/sub.lua 注意目录的命名
<function List here, this module will be see as mod.lua's sub modle>
return table
When you require a module called mod.sub, require queries first the table
package.loaded and then the table package.preload using the original module
name “mod.sub” as the key; here, the dot is just a character like any other in the
module name. 其实根原来的mod 没什么关系吧 ,,都是当一个module 来load, But...->see below:
However, when searching for a file that defines that submodule, require
translates the dot into another character, usually the system’s directory separator
(e.g., ‘/’ for UNIX or ‘\’ for Windows). After the translation, require searches
for the resulting name like any other name. For instance, assume ‘/’ as the
directory separator and the following path:
./?.lua;/usr/local/lua/?.lua;/usr/local/lua/?/init.lua
The call require"a.b" will try to open the following files:
./a/b.lua -- 还是有关系的sub model 是在原来mod 下面的目录的
/usr/local/lua/a/b.lua
/usr/local/lua/a/b/init.lua
This behavior allows all modules of a package to live in a single directory.
We will return here to ba continue when I know know to write a C libary.