0%

lua

start

运行lua程序的方式:
  • lua的交互模式:

    1
    2
    > print("Hello World")
    >Hello World
  • lua+文件

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    ksance0@ubuntu:~/lua/workspace$ lua func.lua 
    enter a num
    3
    6
    -- defines a factorial function //comment
    function fact (n)
    if n == 0 then
    return 1
    else
    return n * fact(n-1)
    end
    end

    print("enter a number:")
    a = io.read("*number") -- read a number
    print(fact(a))
chunk概念:
  • Each piece of code that Lua executes, such as a file or a single line in interactive mode, is a chunk. More specifically, a chunk is simply a sequence of statements.
    所以一次输入:文件或者交互模式下的语句都是一个chunk;
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    下面四个是相同的chunk:
    a = 1
    b = a*2

    a = 1;
    b = a*2;

    a = 1 ; b = a*2

    a = 1 b = a*2 -- ugly, but valid
    同一行可以用;隔开
退出交互模式,在加载lua文件运行:
  • 退出交互模式:just type end-of-file (ctrl-D in Unix, ctrl-Z in DOS/Windows), or call the exit function, from the Operating System library (you have to type os.exit()).

  • 在下加载:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    a.lua: x=1
    b.lua: print(x)
    ksance0@ubuntu:~/lua/workspace$ lua -la -lb
    1
    Lua 5.2.3 Copyright (C) 1994-2013 Lua.org, PUC-Rio
    >
    加-i参数时:
    ksance0@ubuntu:~/lua/workspace$ lua -i -la -lb
    Lua 5.2.3 Copyright (C) 1994-2013 Lua.org, PUC-Rio
    1
    >
  • 交互模式下加载:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     -- file 'lib1.lua'

    function norm (x, y)
    local n2 = x^2 + y^2
    return math.sqrt(n2)
    end

    function twice (x)
    return 2*x
    end
    Then, in interactive mode, you can type
    > dofile("lib1.lua") -- load your library
    > n = norm(3.4, 1.0)
    > print(twice(n)) --> 7.0880180586677
    全局变量

    全局变量是不需要先声明的变量,它初值为nil:

    1
    2
    3
    print(b)  --> nil
    b = 10
    print(b) --> 10

    当想删除一个全局变量:b=nil
    一个全局变量存在当且仅当它不为空

    一些词法约定
  • 标识符可以是字符,下划线和数字,但是不能以数字开头:建议不用下划线开头,避免冲突

  • 保留字:
    and break do else elseif
    end false for function if
    in local nil not or
    repeat return then true until
    while

  • lua大小写敏感

  • 如何注释:

    1
    --   eg: --a=10  
  • 注释多行:

    1
    2
    3
    4
    5
    6
    7
    --[[
    print(10) -- no action (comment)
    --]]
    错误用法:
    ---[[
    print(10) -- no action (comment)
    --]]
    lua解释器介绍:
  • lua解释器也叫lua.c,因为是由lua.c执行: /usr/local/bin/lua

  • 脚本开头指定解释器:

    1
    2
    3
    4
    5
    #!/usr/local/bin/lua 或#!/usr/bin/env lua指定lua解释器后,不用lua filename.lua执行,即直接./xxx.lua
    否则: lua [options] [script [args]]
    那么这里options有哪些呢?
    1)-e 允许直接运行: prompt> lua -e "print(math.sin(12))" --> -0.53657291800043
    2) -i允许加载文件到lua交互模式运行: prompt> lua -i -l a.lua -e "x = 10"
  • 改变lua交互模式表示:

    1
    2
    3
    4
    ksance0@ubuntu:~/lua/workspace$  lua -i -e "_PROMPT='lua32> '"
    Lua 5.2.3 Copyright (C) 1994-2013 Lua.org, PUC-Rio
    lua32>
    //这个_PROMPT是一个内定全局变量
  • lua和它的输入参数:

    1
    2
    3
    4
    5
    6
    7
    8
                 lua -e "sin=math.sin" script a b
    lua collects the arguments as follows:
    arg[-3] = "lua"
    arg[-2] = "-e"
    arg[-1] = "sin=math.sin"
    arg[0] = "script"
    arg[1] = "a"
    arg[2] = "b"
  • 更多:
    在开始运行参数之前,lua会查找一个名为LUA_INIT的环境变量。如果有这样一个变量,并且它的内容是@filename,那么lua加载给定的文件。如果定义了LUA_INIT但没有以’ @开始,那么lua会假设它包含lua代码并运行它。在配置独立解释器时,这个变量提供了强大的功能,因为您在配置中使用了Lua的全部功能。您可以预加载包、更改提示符和路径、定义自己的函数、重命名或删除函数,等等。

type_value:

8种类型
1
2
3
4
5
6
7
8
9

nil, boolean, number, string, userdata, function, thread, and table.
print(type("Hello world")) --> string
print(type(10.4*3)) --> number
print(type(print)) --> function
print(type(type)) --> function
print(type(true)) --> boolean
print(type(nil)) --> nil
print(type(type(X))) --> string //这个是string的原因是type(X)结果终归是一个string
值可以是任意类型:
1
2
3
4
5
6
7
print(type(a))   --> nil   (`a' is not initialized)
a = 10
print(type(a)) --> number
a = "a string!!"
print(type(a)) --> string
a = print -- yes, this is valid!
a(type(a)) --> function
Nil类型:

Nil是一个单值类型,只有一个值nil,它是global 变量的默认值,也可以用来赋值以删除全局变量,它表示non-value

Booleans:

包括true和false两个取值,条件语句中false和nil为false,其他为true;
注意:不像其他脚本语言:lua中,0和空字符串表示为true;

Number:

lua中数字类型只有double和float,lua没有整型数,因为它不需要;
以下是有效的数字常量:4 0.4 4.57e-3 0.3e12 5e+20
注意lua用double和float并不比整数效率差;

String
  • 和C一样是一串字符,8位每个,不可变,可赋值;

  • string在lua中时自动内存管理的对象,和其他lua对象一样;

  • lua可以处理很长的字符串:Programs that manipulate strings with 100K or 1M characters are not unusual in Lua.

  • 可以用单引号或双引号: a=’a linx’ / a=”line”

  • 可以和C一样用转义字符;“alo\n123\”和“\97lo\10\04923”具有相同的值:97是a的ASCII代码,10是换行代码

  • 可以用[[….]]来分隔文本字符串;

  • 连接字符串:

    1
    2
    3
    4
    5
    6
    7
    print("10" + 1)           --> 11
    print("10 + 1") --> 10 + 1
    print("-5.3e-10"*"2") --> -1.06e-09
    print("hello" + 1) -- ERROR (cannot convert "hello")
    print(10 .. 20) --> 1020
    print(tostring(10) == "10") --> true
    print(10 .. "" == "10") --> true
    table
  • 关联数组:key可以是除nil之外的任何类型,无固定长度,动态增长;当我们用io.read时,可以说是读read为key的一个table,在io package中;

  • table是对象,通过构造表达式可以构造一个table:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    a = {}     -- create a table and store its reference in `a'
    k = "x"
    a[k] = 10 -- new entry, with key="x" and value=10
    a[20] = "great" -- new entry, with key=20 and value="great"
    print(a["x"]) --> 10
    k = 20
    print(a[k]) --> "great"
    a["x"] = a["x"] + 1 -- increments entry "x"
    print(a["x"]) --> 11
  • 保存表的变量和表本身无关:直到最后一个引用删除,表才被删除和释放内存

    1
    2
    3
    4
    5
    6
    7
    8
    a = {}
    a["x"] = 10
    b = a -- `b' refers to the same table as `a'
    print(b["x"]) --> 10
    b["x"] = 20
    print(a["x"]) --> 20
    a = nil -- now only `b' still refers to the table
    b = nil -- now there are no references left to the table
  • 表可以容纳多种类型的值:

    1
    2
    3
    4
    5
    6
    7
    a = {}     -- empty table
    -- create 1000 new entries
    for i=1,1000 do a[i] = i*2 end
    print(a[9]) --> 18
    a["x"] = 10
    print(a["x"]) --> 10
    print(a["y"]) --> nil 值未被初始化时,为nil,和全局变量一样
  • 注意索引类型的不同

function:

像python一样,lua中的函数也可以像变量一样传递,或者说他就是变量;lua也可以调用C函数

Userdata and Threads:TODO

expressions:

四则运算:+-*/ -(负),乘方^
关系运算符: < > <= >= == ~=,lua根据类型比较,结果为false or true, nil只会等于它本身
1
2
3
4
5
6
lua比较tables, userdata, and functions by reference,所以这里必须是指向同个object才相等
eg:
a = {}; a.x = 1; a.y = 0
b = {}; b.x = 1; b.y = 0
c = a
you have that a==c but a~=b.
逻辑运算符:and or not,三目运算符: a ? b : c
1
2
3
4
print(not nil)      --> true
print(not false) --> true
print(not 0) --> false
print(not not nil) --> false
连接符:..
1
2
3
4
5
print("Hello " .. "World")  --> Hello World
print(0 .. 1) --> 01
a = "Hello"
print(a .. " World") --> Hello World
print(a) --> Hello
符号优先级:
1
2
3
4
5
6
7
8
^
not - (unary)
* /
+ -
..
< > <= >= ~= ==
and
or
table构造器:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
1) {}  eg:a={}
2) days = {"Sunday", "Monday", "Tuesday", "Wednesday",
"Thursday", "Friday", "Saturday"} //索引是数字
3) 表达式:tab = {sin(1), sin(2), sin(3), sin(4),
sin(5), sin(6), sin(7), sin(8)}
4) 复杂的赋值:
w = {x=0, y=0, label="console"}
x = {sin(0), sin(1), sin(2)}
w[1] = "another field"
x.f = w
print(w["x"]) --> 0
print(w[1]) --> another field
print(x.f[1]) --> another field
w.x = nil -- remove field "x"
5) 应用:利用table构建链表:
list = nil
for line in io.lines() do
list = {next=list, value=line}
end
6) 复杂的例子测试;2待测试:https://www.lua.org/pil/3.6.html

语句Statements:

赋值
1
a="hel".."low"
  • 多重赋值:

    1
    2
    3
    4
    5
    6
    lua32> t,e=3,4
    lua32> print(t..e)
    34
    利用多重赋值交换值:
    x, y = y, x -- swap `x' for `y'
    a[i], a[j] = a[j], a[i] -- swap `a[i]' for `a[j]'
  • 不足补nil,太多参数则丢弃

    1
    2
    3
    4
    5
    6
    a, b, c = 0, 1
    print(a,b,c) --> 0 1 nil
    a, b = a+1, b+1, b+2 -- value of b+2 is ignored
    print(a,b) --> 1 2
    a, b, c = 0
    print(a,b,c) --> 0 nil nil
  • 使用函数返回的参数:

    1
    2
    3
    4
    5
    6
    7
    8
     lua32> function f()
    >> return 1,2
    >> end
    lua32> a,b=f()
    lua32> print(a);print(b)
    1
    2
    lua32>
本地变量和块
  • 本地变量定义
    1
    2
    j = 10         -- global variable
    local i = 1 -- local variable
  • 本地变量作用域
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    chunk, function,流程控制块
    eg:xxx.lua: 交互模式下不生效;
    x = 10
    local i = 1 -- local to the chunk

    while i<=x do
    local x = i*2 -- local to the while body
    print(x) --> 2, 4, 6, 8, ...
    i = i + 1
    end

    if i > 20 then
    local x -- local to the "then" body
    x = 20
    print(x + 2)
    else
    print(x) --> 10 (the global one)
    end

    print(x) --> 10 (the global one)
  • 交互模式下:
    1
    2
    3
    4
    5
     lua32> local yy=3
    lua32> print(yy)
    nil
    lua32>
    从上面例子看到,下一行就是新的chunk,所以yy作用域只在那一行;
  • 用法举例:
    1
    2
    3
    4
    5
    6
    7
    local a, b = 1, 10
    if a<b then
    print(a) --> 1
    local a -- `= nil' is implicit
    print(a) --> nil
    end -- ends the block started at `then'
    print(a,b) --> 1 10
  • 强制指定作用域:
    1
    2
    3
    4
    5
    6
    7
    do
    local a2 = 2*a
    local d = sqrt(b^2 - 4*a*c)
    x1 = (-b + d)/a2
    x2 = (-b - d)/a2
    end -- scope of `a2' and `d' ends here
    print(x1, x2)
    控制流程:
  • 简介:有if,while,repeat,for,end,until
  • if语句:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    if op == "+" then
    r = a + b
    elseif op == "-" then
    r = a - b
    elseif op == "*" then
    r = a*b
    elseif op == "/" then
    r = a/b
    else
    error("invalid operation")
    end
  • while:
    1
    2
    3
    4
    5
    local i = 1
    while a[i] do
    print(a[i])
    i = i + 1
    end
  • repeat:执行至少一次,直到条件不满足:
    1
    2
    3
    4
    5
    -- print the first non-empty line
    repeat
    line = io.read()
    until line ~= ""
    print(line)
  • for:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    基本语法:
    for var=exp1,exp2,exp3 do
    something
    end
    参数:exp1,exp2 范围,如1,10 /10,1
    exp3:可选 ,表示递增或递减的步长,eg: 1,10,2 则循环:1,3,5,7,9,无指定则默认为1;
    for i=1,f(x) do print(i) end
    for i=10,1,1 do print(i) end; 无结果
    for i=10,1,0 do print(i) end; 死循环
    注意i这里是本地变量,若需使用如下:可以使用break退出循环
    -- find a value in a list
    local found = nil
    for i=1,a.n do
    if a[i] == value then
    found = i -- save value of `i'
    break
    end
    end
    print(found)
  • for 2:遍历结构中的所有值:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    -- print all values of array `a'
    for i,v in ipairs(a) do print(v) end
    days = {"Sunday", "Monday", "Tuesday", "Wednesday",
    "Thursday", "Friday", "Saturday"}
    lua32> for i,v in ipairs(days) do
    revDays[v] = i
    print(revDays[v]);print(v)
    end
    1
    Sunday
    2
    Monday
    3
    Tuesday
    4
    Wednesday
    5
    Thursday
    6
    Friday
    7
    Saturday
    lua32>
  • break,return ;

function:

函数基本格式:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
 -- add all elements of array `a'
function add (a)
local sum = 0
for i,v in ipairs(a) do
sum = sum + v
end
return sum
end
支持可选参数:
function f(a, b) return a or b end
函数 参数
f(3) a=3, b=nil
f(3, 4) a=3, b=4
f(3, 4, 5) a=3, b=4 (5 is discarded)
函数可以返回多个参数:
1
2
3
function foo0 () end                  -- returns no results
function foo1 () return 'a' end -- returns 1 result
function foo2 () return 'a','b' end -- returns 2 results
函数的可选参数:
1
2
3
4
5
6
7
8
9
10
function g (a, b, ...) end

CALL PARAMETERS

g(3) a=3, b=nil, arg={n=0}
g(3, 4) a=3, b=4, arg={n=0}
g(3, 4, 5, 8) a=3, b=4, arg={5, 8; n=2}
function select (n, ...)
return arg[n]
end

#####函数位置参数:

1
2
3
4
5
6
lua不提供位置参数的功能,但是可以通过传递table来间接指定对应参数:
用法:
rename{old="temp.lua", new="temp1.lua"}
function rename (arg)
return os.rename(arg.old, arg.new)
end
高级函数
  • 函数作为值传递:
    1
    2
    3
    4
    5
    6
    a = {p = print}
    a.p("Hello World") --> Hello World
    print = math.sin -- `print' now refers to the sine function
    a.p(print(1)) --> 0.841470
    sin = a.p -- `sin' now refers to the print function
    sin(10, 20) --> 10 20
  • 函数的参数也可以是函数:
    1
    2
    3
    table.sort(network, function (a,b)
    return (a.name > b.name)
    end)
    高级函数-闭包
    1
    2
    3
    4
    5
    6
    定义:一个函数内再定义一个函数,内部函数可以用外部函数的变量
    names = {"Peter", "Paul", "Mary"}
    grades = {Mary = 10, Paul = 7, Peter = 8}
    table.sort(names, function (n1, n2)
    return grades[n1] > grades[n2] -- compare the grades
    end)
高级函数:非全局函数:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
用法举例:
Lib = {}
Lib.foo = function (x,y) return x + y end
Lib.goo = function (x,y) return x - y end

Lib = {}
function Lib.foo (x,y)
return x + y
end
function Lib.goo (x,y)
return x - y
end

local f = function (...)
...
end

local g = function (...)
...
f() -- external local `f' is visible here
...
end
高级函数: 尾调用

迭代器

编译执行和错误处理

dofile,loadfile,后者加载文件并编译它
loadstring函数
require:

是lua的高等级函数,用于加载和运行库,大致的说,和dofile一样,不过require支持搜索文件路径和避免重复加载;

c 包:在lua中加载c库的方式:
1
2
3
local path = "/usr/local/lua/lib/libluasocket.so"
local f = loadlib(path, "luaopen_socket")
windows则用.dll
错误处理:
  我们必须以最好的方式处理错误。因为Lua是一种扩展语言,通常嵌入到应用程序中,所以当发生错误时,它不能简单地崩溃或退出。相反,每当出现错误时,Lua会结束当前块并返回应用程序。
错误处理方式:

对许多应用程序,不需要去对lua做错误处理,通常应用程序自己会做处理;lua的所有运行,开始于应用程序的一个调用,这个调用让lua运行一个chunk,若出现了错误,会返回错误码,应用程序根据这个来做处理;
若想在lua中处理错误,则:使用pcall

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
eg:
function foo ()
...
if unexpected_condition then error() end
...
print(a[i]) -- potential error: `a' may not be a table
...
end

function foo ()
...
if unexpected_condition then error() end
...
print(a[i]) -- potential error: `a' may not be a table
...
end
错误信息和traceback

通常,当发生错误时,我们需要更多的调试信息,而不仅仅是错误发生的位置。至少,我们需要回溯,显示导致错误的调用的完整堆栈。当pcall返回它的错误消息时,它会销毁堆栈的一部分(从堆栈到错误点的那一部分)。因此,如果我们想要回溯,我们必须在pcall返回之前构建它。为此,Lua提供了xpcall函数。除了要调用的函数外,它还接收到第二个参数,一个错误处理函数。在出现错误的情况下,Lua在堆栈展开之前调用该错误处理程序,以便它可以使用调试库收集关于错误的任何额外信息。两个常见的错误处理程序是debug.debug,它提供一个Lua提示,以便您可以自己检查错误发生时发生了什么(稍后我们将在讨论调试库时看到更多关于它的内容);和调试。traceback,它使用一个traceback构建一个扩展的错误消息。后者是独立解释器用来构建其错误消息的函数。您还可以调用debug。随时回溯以获取当前执行的回溯
print(debug.traceback())

c如何调用lua? lua_cpp

协程:

协程:协作的线程? 主要用于协作的功能
  Lua提供了我称为非对称协程的方法。这意味着它有一个用于挂起协同程序执行的函数和另一个用于恢复挂起的协同程序的函数。其他一些语言提供了对称协同程序,其中只有一个函数可以将控制权从一个协同程序转移到另一个协同程序。

lua的协程函数:

  • 创建协程:
    1
    2
    3
    4
    co = coroutine.create(function ()
    print("hi")
    end)

  • 打印
    print(co)
  • 协程的状态
    1
    2
    3
    print(coroutine.status(co))   --> suspended
    coroutine.resume(co) --> hi
    print(coroutine.status(co)) --> dead 协程运行完就死了;
  • 协程操作:
    yield:
    挂起,唤醒后再接着运行;
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    co = coroutine.create(function ()
    for i=1,10 do
    print("co", i)
    coroutine.yield()
    end
    end)
    coroutine.resume(co) --> co 1
    print(coroutine.status(co)) --> suspended
    coroutine.resume(co) --> co 2
    coroutine.resume(co) --> co 3
    ...
    coroutine.resume(co) --> co 10
    coroutine.resume(co) -- prints nothing
    运行结束后 print(coroutine.resume(co))
    --> false cannot resume dead coroutine:
  • lua协程运行在protocted模式,故不会显示error,若发生,但是会返回给resume调用:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    1)参数传递:
    co = coroutine.create(function (a,b,c)
    print("co", a,b,c)
    end)
    coroutine.resume(co, 1, 2, 3) --> co 1 2 3
    2resume返回例子:resume-yield can exchange data between them.
    co = coroutine.create(function (a,b)
    coroutine.yield(a + b, a - b)
    end)
    print(coroutine.resume(co, 20, 10))
    结果: true 30 10
    3)或者yield返回任何传递的
    co = coroutine.create (function ()
    print("co", coroutine.yield())
    end)
    coroutine.resume(co)
    coroutine.resume(co, 4, 5) --> co 4 5
    4)函数返回值:
    co = coroutine.create(function ()
    return 6, 7
    end)
    print(coroutine.resume(co)) --> true 6 7
使用范例:

一个循环挂起,另一个唤醒;生产者-消费者
同步

Pipes and Filters 消费-生产者例子:
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
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
first:
function producer ()
while true do
local x = io.read() -- produce new value
send(x) -- send to consumer
end
end

function consumer ()
while true do
local x = receive() -- receive from producer
io.write(x, "\n") -- consume new value
end
end

完全例子和send,receive实现:
function receive (prod)
local status, value = coroutine.resume(prod)
return value
end

function send (x)
coroutine.yield(x)
end

function producer ()
return coroutine.create(function ()
while true do
local x = io.read() -- produce new value
send(x)
end
end)
end

function filter (prod)
return coroutine.create(function ()
local line = 1
while true do
local x = receive(prod) -- get new value
x = string.format("%5d %s", line, x)
send(x) -- send it to consumer
line = line + 1
end
end)
end

function consumer (prod)
while true do
local x = receive(prod) -- get new value
io.write(x, "\n") -- consume new value
end
end
The final bit simply creates the components it needs, connects them, and starts the final consumer:
p = producer()
f = filter(p)
consumer(f)
Or better yet:
consumer(filter(producer()))

表和对象:

All structures that other languages offer—arrays, records, lists, queues, sets—are represented with tables in Lua.

复杂的结构在lua中是table:
  • 用table表示数组:
    1
    2
    3
    4
    a = {}    -- new array
    for i=1, 1000 do
    a[i] = 0
    end
  • 矩阵和多维数组:
    1
    2
    3
    4
    5
    6
    7
    mt = {}          -- create the matrix
    for i=1,N do
    mt[i] = {} -- create a new row
    for j=1,M do
    mt[i][j] = 0
    end
    end
  • 链表:
    1
    2
    3
    4
    5
    6
    7
    list = {next = list, value = v}
    To traverse the list, we write:
    local l = list
    while l do
    print(l.value)
    l = l.next
    end
  • queue
  • sets
  • stringbuffer
    文件和存储
  • Serialization序列化
  1. 保存表的方式–非循环
  2. 保存表的方式–循环
    原表和关系运算:
  • 表操作:通常表的操作无非key-value等,可预测,所以提供了一些接口 ,以及原表来提供强大的功能;
  • 原表提供算术相关的表级别操作:https://www.lua.org/pil/13.1.html
  • 原表提供关系运算表级别操作:https://www.lua.org/pil/13.2.html
  • 已定义的库的表操作
  • 表操作如下:
  1. __index
  2. __newindex
  3. 默认值表
  4. 跟踪表操作
  5. 只读表

环境和_G

介绍:
  • lua保存它所有的全局变量在一个常规表里,被叫做环境,更准确的说,是保存在几个环境中,这里忽略多重性;
  • 这个常规表环境是_G,_G._G==_G
    例如,打印当前环境的所有全局变量:
    1
    for n in pairs(_G) do print(n) end
    访问全局变量的方式:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
     loadstring("value = " .. varname)()
    or
    value = loadstring("return " .. varname)()
    value = _G[varname]---效率高,常见
    赋值:_G[varname] = value
    使用举例:
    function setfield (f, v)
    local t = _G -- start with the table of globals
    for w, d in string.gfind(f, "([%w_]+)(.?)") do
    if d == "." then -- not last field?
    t[w] = t[w] or {} -- create table if absent
    t = t[w] -- get the table
    else -- last field
    t[w] = v -- do the assignment
    end
    end
    end
    定义全局变量
    非全局环境 :https://www.lua.org/pil/14.3.html
    未声明的全局变量,例如相关的库,会带来问题
    可以通过setenv改变环境
    1
    2
    3
    4
    5
    6
      a = 1   -- create a global variable
    -- change current environment to a new empty table
    setfenv(1, {})
    print(a)
    results in
    stdin:5: attempt to call global `print' (a nil value)
    面向对象编程
    weak tables