chapter15 Modules and Packages-02


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.






15.2 The Basic Approach for Writing Modules in Lua

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.






评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值