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")

 

运行现象:

Lua如何管理”package”_编译器