LUA 进阶

2.1k 词

环境

1
lua -e "for k,v in pairs(_G) do print(k,v) end" | sort
  • lua全局环境变量保存在_G的table中,内容如下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    assert  function: 0
    collectgarbage function: 0x99f5bd0
    coroutine table: 0x99f6718
    debug table: 0x99f97d0
    dofile function: 0x99f5c88
    error function: 0x99f5cc0
    gcinfo function: 0x99f5c10
    getfenv function: 0x99f5c48
    getmetatable function: 0x99f5de0
    _G table: 0x99f5450
    io table: 0x99f79e8
    ipairs function: 0x99f59a0
    loadfile function: 0x99f5e20
    load function: 0x99f5cf8
    loadstring function: 0x99f5d30
    math table: 0x99f8dd0
    module function: 0x99f6ce0
    newproxy function: 0x99f66b0
    next function: 0x99f5d68
    os table: 0x99f81f0
    package table: 0x99f6a50
    pairs function: 0x99f5a00
    pcall function: 0x99f5da0
    print function: 0x99f6020
    rawequal function: 0x99f6058
    rawget function: 0x99f6090
    rawset function: 0x99f60c8
    require function: 0x99f6f88
    select function: 0x99f5478
    setfenv function: 0x99f5e58
    setmetatable function: 0x99f5e90
    string table: 0x99f65b8
    table table: 0x99f6828
    tonumber function: 0x99f5ed0
    tostring function: 0x99f5f08
    type function: 0x99f5f40
    unpack function: 0x99f5f78
    _VERSION Lua 5.1
    xpcall function: 0x99f5fb0
  • setfenv(set function environment)改变一个函数的环境,该环境参数是一个函数层级和一个table,函数层级1表示当前函数,2表示调用当前函数的函数,以此类推

    1
    setfenv(1, {g = _G})
  • 由于函数继承创建其函数的环境,所以一个程序块改变了自己的环境,后续由它创建的函数都共享新环境

模块和包

require

  • require调用返回一个模块函数组成的table,并且定义一个包含改table的全局变量
  • require采用一串路径模式,每个模式都包含一个可选的?, require用模块名替换?,来查找这个文件,如果不存在,将寻找下一项。假设路径为

    1
    2
    3
    4
    5
    ?;?.lua;/usr/local/lib/?.lua?;
    执行require "sql"将尝试打开如下文件
    sql
    sql.lua
    /usr/loca/lib/sql.lua
  • require 搜索路径在_G.package.path中定义,如果无法找到将寻找c库,路径在_G.package.cpath中定义

  • 如果模块没有返回值,require返回package.loaded[modename]的值

module函数

1
module(..., package.seeall) 等价于如下代码:
1
2
3
4
5
6
local modname = ...
local M = {}
_G[modename] = M
package.loaded[modename] = M
setmetatable(M, {__index = _G})
setfenv(1, M)

子模块与包

lua支持层级模块,中间使用.分割。比如mod.sub就是sub的子模块,require搜索路径时将.转换为系统路径(/或)

面向对象

  • lua使用冒号(:)隐藏self参数,函数内仍可以通过self参数访问成员

    1
    table.sub(table, 10) => table:sub(10)
  • 示例:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    #!/usr/bin/env lua

    Account = { balance = 0, withdraw = function(v)
    self.balance = self.balance - v
    end }

    function Account:deposit(v)
    self.balance = self.balance + v
    end

    function Account:new(o)
    o = o or {}
    setmetatable(o, self)
    self.__index = self
    return o
    end

    a = Account:new()
    print (a.balance)