lua 学习笔记8

lua 学习笔记8

/**************/
    只读表
/**************/
利用metaMetods我们还可以做到只读的表格.用前面的方法来实现效率上不是很高,所以,现在改成__index直接指向只读表格的内容,而修改__newindex为调用error信息.( 记住: 前面说过了,__index指向表格时,系统会自动查找表格中的key相等的元素,并返回)
下面是实现方法
   — 此函数参数,是一个只读表格
   function readOnly (t)
      local proxy = {}
      local mt = {       — create metatable
        __index = t,
        __newindex = function (t,k,v)
          error("attempt to update a read-only table", 2)
        end
      }
      setmetatable(proxy, mt)
      return proxy
    end
用法例如:
    days = readOnly{"Sunday", "Monday", "Tuesday", "Wednesday",
             "Thursday", "Friday", "Saturday"}
   
    print(days[1])     –> Sunday
    days[2] = "Noday"
    stdin:1: attempt to update a read-only table
/*****************/
    设置环境
/*****************/
    Lua keeps all its global variables in a regular table, called the environment. (To be more precise, Lua keeps its "global" variables in several environments, but we will ignore this multiplicity for a while.) One advantage of this structure is that it simplifies the internal implementation of Lua, because there is no need for a different data structure for global variables. The other (actually the main) advantage is that we can manipulate this table as any other table. To facilitate such manipulations, Lua stores the environment itself in a global variable _G. (Yes, _G._G is equal to _G.)
    You can change the environment of a function with the setfenv function (set function environment). It receives the function and the new environment. Instead of the function itself, you can also give a number, meaning the active function at that given stack level. Number 1 means the current function, number 2 means the function calling the current function (which is handy to write auxiliary functions that change the environment of their caller), and so on.
    例如:
    a = 1   — create a global variable
    — change current environment
    setfenv(1, {_G = _G})
    _G.print(a)      –> nil
    _G.print(_G.a)   –> 1
    Now, when you access the "global" _G, its value is the old environment, wherein you will find the field print.
/*************************/
   包(package)的实现方法
/*************************/
1.用表格来实现
例如:
    complex = {}
   
    function complex.new (r, i) return {r=r, i=i} end
   
    — defines a constant `i’
    complex.i = complex.new(0, 1)
   
    function complex.add (c1, 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.inv (c)
      local n = c.r^2 + c.i^2
      return complex.new(c.r/n, -c.i/n)
    end
   
    return complex
  元素的私有化:
    local function checkComplex (c)
    end
   
    local function new (r, i) return {r=r, i=i} end
   
    local function add (c1, c2)
    end
    complex = {
      new = new,
      add = add,
    }
    这样做,外界看到包里只有new,add而没有checkComplex,达到了私有化的目的.另外这些元素在访问时,也不需要加上繁琐的"complex."这个前缀.
2.利用the Global Table
The simplest technique does little more than that. Once the package has an exclusive environment, not only all its functions share this table, but also all its global variables go to this table. Therefore, we can declare all public functions as global variables and they will go to a separate table automatically. All the package has to do is to register this table as the package name. The next code fragment illustrates this technique for the complex library:
    local P = {}
    complex = P
    setfenv(1, P)
Now, when we declare function add, it goes to complex.add:
    function add (c1, c2)
      return new(c1.r + c2.r, c1.i + c2.i)
    end
Moreover, we can call other functions from this package without any prefix. For instance, add gets new from its environment, that is, it gets complex.new.
另外如果在文件中加上如下语句
    local P = {}   — package
    if _REQUIREDNAME == nil then
      complex = P
    else
      _G[_REQUIREDNAME] = P
    end
    setfenv(1, P)
则在包中出现_REQUIREDNAME,那么改值就成为包名
上面的做法,并没有包含_G环境,所以一些_G表的内容无法访问,可以添加一个local变量指向_G
    local P = {}
    pack = P
    local _G = _G
    setfenv(1, P)
更进一步,可以只访问一些自己需要的内容
A more disciplined approach is to declare as locals only the functions you need, or at most the packages you need:
    local P = {}
    pack = P
   
    — Import Section:
    — declare everything this package needs from outside
    local sqrt = math.sqrt
    local io = io
   
    — no more external access after this point
    setfenv(1, P)
/*****************************/
   本地变量和全局变量一个问题
/*****************************/
in the function body, the local is not yet defined. Therefore, that expression calls a global not the local one.
看看下面例子就能想明白了,如果有本地变量,则优先处理本地变量,否则,先处理全局的变量.
程序1:
_G["a"]=10
a=12
function t()
 print(_G.a)
end
t()
结果输出:
— output:12
程序2:
local a=11
_G["a"]=10
a=12
function t()
 print(_G.a)
end
t()
结果输出:
— output:10
程序3
local a=11
_G["a"]=10
a=12
function t()
 print(a)
end
t()
结果输出:
— output:12
/*******************/
      解开包
/*******************/
It is easy to write a function that unpacks a package, putting all its names into the global namespace:
    function openpackage (ns)
       for n,v in pairs(ns) do
        if _G[n] ~= nil then
          error("name clash: " .. n .. " is already defined")
        end
        _G[n] = v
      end
    end
   
    openpackage(complex)
    c1 = mul(new(10, 20), i)
/***************/
   autoload
/***************/
autoload, which only loads a function if the function is actually used by the program. When we load an autoload package, it creates an empty table to represent the package and sets the __index metamethod of the table to do the autoload. Then, when we call any function that is not yet loaded, the __index metamethod is invoked to load it. Subsequent calls find the function already loaded; therefore, they do not activate the metamethod.
A simple way to implement autoload can be as follows. Each function is defined in an auxiliary file. (There can be more than one function in each file.) Each of these files defines its functions in a standard way, for instance like here:
    function pack1.foo ()
      …
    end
   
    function pack1.goo ()
      …
    end
However, the file does not create the package, because the package already exists when the function is loaded.
In the main package we define an auxiliary table that describes where we can find each function:
    local location = {
      foo = "/usr/local/lua/lib/pack1_1.lua",
      goo = "/usr/local/lua/lib/pack1_1.lua",
      foo1 = "/usr/local/lua/lib/pack1_2.lua",
      goo1 = "/usr/local/lua/lib/pack1_3.lua",
    }
Then we create the package and define its metamethod:
    pack1 = {}
   
    setmetatable(pack1, {__index = function (t, funcname)
      local file = location[funcname]
      if not file then
        error("package pack1 does not define " .. funcname)
      end
      assert(loadfile(file))()     — load and run definition
      return t[funcname]           — return the function
    end})
   
    return pack1
After loading this package, the first time the program executes pack1.foo() it will invoke that __index metamethod, which is quite simple. It checks that the function has a corresponding file and loads that file. The only subtlety is that it must not only load the file, but also return the function as the result of the access.
Because the entire system is written in Lua, it is easy to change its behavior. For instance, the functions may be defined in C, with the metamethod using loadlib to load them. Or we can set a metamethod in the global table to autoload entire packages. The possibilities are endless.

2 thoughts on “lua 学习笔记8

  1. Hi,Do you need digital signage, digital sign, ad players and ad displays? Please go Here:www.amberdigital.com.hk(Amberdigital).we have explored and developed the international market with professionalism. We have built a widespread marketing network, and set up a capable management team dedicated to provide beyond-expectation services to our customers.

    amberdigital Contact Us
    E-mail:sstar@netvigator.com
    website:www.amberdigital.com.hk
    alibaba:amberdigital.en.alibaba.com[i

  2. wow power leveling
    wow power leveling
    wow power leveling
    wow power leveling
    wow power leveling
    wow power leveling
    wow power leveling
    wow power leveling
    wow power leveling
    wow power leveling
    wow power leveling
    wow power leveling
    wow power leveling
    wow power leveling
    wow power leveling
    wow power leveling
    wow power leveling
    wow power leveling
    wow power leveling
    wow power leveling
    wow power leveling
    wow power leveling
    wow power leveling
    wow power leveling
    wow power leveling
    wow power leveling
    wow power leveling
    wow power leveling
    wow power leveling
    wow power leveling
    wow power leveling
    wow power leveling
    wow power leveling
    wow power leveling -229065167619293

Leave a Reply

Your email address will not be published. Required fields are marked *