Lua如何管理”package”
方式一:
私有方法和变量都需要显式定义为local类型的,这很容易造成错误。一旦不小心漏写,就又将方法定义为全局的了。
”package”中方法和变量的定义都需要加上”package”名字前缀。
-- "complex.lua"文件中 local complex = {} --[[ 在5.0之后,Lua用了一种类似于寄存器的虚拟机模式,Lua用栈来储存其寄存器。每一个活动的函数,Lua都会对其分配一个栈,这个栈用来储存函数里的活动记录。 lua的编译器将local变量存储至寄存器,对local变量的操作就相当于直接对寄存器进行操作,对global变量的操作要先获取变量,然后才能对其进一步操作,自然局部变量比全局变量快。 对于全局变量,一是内存访问不如寄存器快,二是可能影响到cache line,对于lua这个东西,全局变量是通过一个table访问的,又是一级间接访问,就更慢了。--]] function complex.new (r, i) return {r=r, i=i} end -- 声明私有变量和方法,需要加上local local function checkComplex (c) if not ((type(c) == "table") and tonumber(c.r) and tonumber(c.i)) then error("bad complex number", 3) end end complex.i = complex.new(0, 1) function complex.add (c1, c2) checkComplex(c1); checkComplex(c2); return complex.new(c1.r + c2.r, c1.i + c2.i) end function complex.sub (c1, c2) return complex.new(c1.r - c2.r, c1.i - c2.i) end function complex.mul (c1, c2) return complex.new(c1.r*c2.r - c1.i*c2.i, c1.r*c2.i + c1.i*c2.r) end function complex.div (c1, c2) local n = c2.r^2 + c2.i^2 return complex.new( (c1.r * c2.r + c1.i * c2.i) / n, (c1.i * c2.r - c1.r * c2.i) / n ) end return complex
方式二:
优化了”package”中方法的定义方式,使得无论是公有还是私有方法都摆脱了”package”名字前缀。不过与此同时,每个方法都需要显式定义为local类型的,这很容易造成错误。一旦不小心漏写,就又将方法定义为全局的了。
-- "complex.lua"文件中 local complex = {} --[[ 在5.0之后,Lua用了一种类似于寄存器的虚拟机模式,Lua用栈来储存其寄存器。每一个活动的函数,Lua都会对其分配一个栈,这个栈用来储存函数里的活动记录。 lua的编译器将local变量存储至寄存器,对local变量的操作就相当于直接对寄存器进行操作,对global变量的操作要先获取变量,然后才能对其进一步操作,自然局部变量比全局变量快。 对于全局变量,一是内存访问不如寄存器快,二是可能影响到cache line,对于lua这个东西,全局变量是通过一个table访问的,又是一级间接访问,就更慢了。--]] -- 以下的所有方法在定义时都去掉了前缀,并且均声明为私有方法("local")。 local function new (r, i) return {r=r, i=i} end local function checkComplex (c) if not ((type(c) == "table") and tonumber(c.r) and tonumber(c.i)) then error("bad complex number", 3) end end local i = new(0, 1) local function add (c1, c2) checkComplex(c1); checkComplex(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 div (c1, c2) local n = c2.r^2 + c2.i^2 return new( (c1.r * c2.r + c1.i * c2.i) / n, (c1.i * c2.r - c1.r * c2.i) / n ) end -- 公有的方法才放在"complex"表中导出。 complex = { new = new, add = add, sub = sub, mul = mul, div = div, i = i, } return complex
方式三:
注意: 这种方式有一个有趣的副作用,例如你为了安全性,屏蔽了_ENV中的io库(io.open(),io.read(),io.write()等),但别人可以通过你提供的”package”访问你屏蔽的函数(例如complex.io.write()等)。
-- "complex.lua"文件中 local complex = {} --[[ 在5.0之后,Lua用了一种类似于寄存器的虚拟机模式,Lua用栈来储存其寄存器。每一个活动的函数,Lua都会对其分配一个栈,这个栈用来储存函数里的活动记录。 lua的编译器将local变量存储至寄存器,对local变量的操作就相当于直接对寄存器进行操作,对global变量的操作要先获取变量,然后才能对其进一步操作,自然局部变量比全局变量快。 对于全局变量,一是内存访问不如寄存器快,二是可能影响到cache line,对于lua这个东西,全局变量是通过一个table访问的,又是一级间接访问,就更慢了。--]] -- 原先环境中的函数或变量需要能被访问,比如下面的"type()"。 setmetatable(complex, {__index = _ENV}) -- 下面的所有函数都会定义在独立的"complex"环境中。 _ENV = complex -- 注意: 这种方式有一个有趣的副作用,例如你为了安全性,屏蔽了_ENV中的io库(io.open(),io.read(),io.write()等),但别人可以通过你提供的”package”访问你屏蔽的函数(例如complex.io.write()等)。 -- 因为在独立的环境中,定义的全局变量存储在"complex"环境中。 -- local变量和函数不能通过complex表访问。 function new (r, i) return {r=r, i=i} end local function checkComplex (c) if not ((type(c) == "table") and tonumber(c.r) and tonumber(c.i)) then error("bad complex number", 3) end end i = new(0, 1) function add (c1, c2) checkComplex(c1); checkComplex(c2); return new(c1.r + c2.r, c1.i + c2.i) end function sub (c1, c2) return new(c1.r - c2.r, c1.i - c2.i) end function mul (c1, c2) return new(c1.r*c2.r - c1.i*c2.i, c1.r*c2.i + c1.i*c2.r) end function div (c1, c2) local n = c2.r^2 + c2.i^2 return new( (c1.r * c2.r + c1.i * c2.i) / n, (c1.i * c2.r - c1.r * c2.i) / n ) end return complex
调用complex.lua
-- "mytest.lua"文件中 -- "require"方式 local cp = require("complex") local c1 = cp.add(cp.i, cp.new(10, 20)) for i, v in pairs(c1) do io.write(string.format("%s = %d", i, v)) end -- "dofile()"方式 local p = dofile("E:\\vsproj\\lua1\\complex.lua") local c2 = p.add(p.i, p.new(10, 20)) for i, v in pairs(c2) do io.write(string.format("%s = %d", i, v)) end io.write("\n")
运行现象: