一、注释:
单行注释 “ -- ”
多行注释 " --[[ --]]"
在 lua 一个代码块 用 do end 来分界,相当于c语言中的 { }。
二、数据类型:
lua中变量不需要申明,给一个变量赋值就相当于声明了一个全局变量,直接用一个没有初始化的变量则会得到值 nil。如果要取消一个变量也可以通过赋值 nil 来实现。局部变量则在变量前面加上 local 关键字。
1、nil lua中的特殊类型,它的值只有 nil 未定义值
2、boolean bool值,lua 中只有 nil 和 false 为 条件假,其它都为真所以 0 和 空串也为真
3、number 数字,整数实数都是它
4、string 字符串:
4.1 字符串是不能修改的。
4.2 lua中字符串和数字会自动进行隐士转换,所以使用的时候要注意可以使用tonumber 或者 tostring 强制将 字符串转换成数字、或数字转换成字符串。
4.3 字符串可以用 双引号或者单引号括起来。
4.4 字符串也可以用 [[ ]] 括起一个字符块,它会按字符块的原始格式保存,并且不会解释其中的转义字符。 如果在 其中包含 a[b[i]] 这中情况的话可以在 中括号中间加任意数量等号做区别 如
[==[
a[b[c]]
测试测试
]==]
4.5 可以用 #strVar 获取字符串长度如 print(#"adfadfadfadf")
5、userdata 可以将 C 数据存放在userdata 变量中,userdata 除了定义 赋值 和 相等比较外没有预定义操作。
6、function 函数,lua 中函数也是变量的一种类型
7、thread 线程,在第九部分详细介绍
8、table lua中table 是最为关键的一个数据类型,很多语言特性都由它实现,后面第七部分专门详细介绍
三、表达式:
数值运行:lua 支持 + - * / ^ (加减乘除幂) 数值运算
关系运算: > 、 < 、 <= 、 >= 、 == 、 ~= 。大于、小于、小于等于、大于等于、等于、不等于
逻辑运算: and、or、not。 注意lua 的 and、or 的返回值不是true和false而是操作数 not 返回值为boolean值
a and b -- 如果 a 为 false 返回 a ,否则返回 b
a or b -- 如果 a 为 true 返回 a,否则返回 b
c语言中的三元表达式 a ? b : c 可以用 ((a and b ) or c ) 实现。
连接运算符:lua中 .. 是连接字符串的连接操作符号。
表构造: lua 中 { } 是一个构造函数,用于构造表。
四、控制结构:
4.1 条件控制 :
if conditions then
elseif conditions then
else
end;
4.2 循环控制:
1、while循环
while condition do
end
2、类似 do while
repeat
until conditions;
3、 for 版本一,和c区别在于,exp,exp2, exp3 表达式都是在运行前运算一次,循环从 var = exp1 到 exp2,增幅为exp3,。exp3默认为1
for var = exp1, exp2, exp3 do
end
4、类似 foreach 循环读取容器中的内容
for k, v in pair(table) do -- 循环直到 k 为 nil
end
等价于
do
local _f, _s, _var = explist -- _f 代表迭代函数、 _s 代表 要遍历的容器,_var 代表循环控制变量
while true do
local var_1, ... , var_n = _f(_s, _var)
_var = var_1
if _var == nil then break end
block
end
end
4.3 break 和 return
break 用于跳出循环用,return 用于函数返回用,lua 中 break 和 return 必须在 block的最后一句,所以有时候你得用 do break end; 这种写法。使它们在block的结尾。
五、函数
lua中函数申明方式为
function 函数名( 参数列表 )
函数执行体
end
5.1 lua 中传参的 是普通变量为按值传递,对象类型为引用传递(table对象),
5.2 lua 中函数也是一种数据类型,所以可以直接将函数赋值给变量。
5.3 lua 中函数可以返回多个值, return 1, 2, 3; 这种是支持的。
5.4 lua 中支持可变的函数参数,和c 一样用 ... (三个点) 代表,然后访问这些参数是通过 arg 这个table来访问。
example:
printResult = ""
function print( ... )
for i, v in ipairs(arg) do
printResult = printResult ... tostring(v);
end
end
5.4 lua 函数有尾调用的概念,当函数a的最后一个操作为单纯的调用一个函数b,那么lua在a调用完这个函数b后,不会再回到函数a调用b地方,也就是说,这时候伟调用有点象goto 语句了。它这种函数调用不会产生栈。
六、闭包
1、lua 中在一个函数中再定义一个函数,则内部函数可以访问外部函数函数的变量。
example:
function funca()
local aa = 10;
function funcb()
print(aa); -- funcb 中访问 funca 中定义的变量 aa
end
funcb();
end
funca(); -- 将输出 10
2、当我们把函数内部在定义的函数作为返回值返回,且这个内部函数有使用外部函数中的变量,那么在内部函数中这个变量的相当于一个 c 语言中的 static 变量。
example:
function newCounter()
local i = 0;
function returnfunc()
i = i+1;
print(i);
end
return returnfunc;
end
c = newCounter(); -- i 值被 函数 newCounter 初始化为 0
c(); -- 输出 1
c(); -- 输出 2
c1 = newCounter(); -- 由于 i 为 local 变量,所以再次调用 newCounter 时又会创建一个新的变量 i
c1(); -- 输出 1
c(); -- 输出 3
c1(); -- 输出 2
7、Table
table 类型实现了关联数组(std::map)。它可以使用除 nil 外的任意值做key索引。
特性:
1、table 是一个不是一个”值"也不是一个”变量“,而是“对象”,也就是说,table 的传递是按引用传递的。
2、Table 的构建用 { } .
2、Table 可以容纳 lua 中各种各样的元素,所以 lua 中 各种封装机制都通过 table 实现。
8、用 c 为 lua 编写包
lua中调用c 写的包,要将c编译成动态库,然后用 loadlib() 加载库,loadlib 函数第一个参数是库的路径,第二个参数是库的 初始化函数名字,成功loadlib 返回初始化库的函数,否则返回 nil。
9、Thread 协同,非抢占式多线程
1、coroutine.create( 过程函数 ) 创建一个协同 thread并返回,create 的参数是,协同thread的调用函数。
2、协同 thread 有三种状态,挂起、运行、停止。刚创建的协同是处于挂起状态的。
3、coroutine.status( 协同变量 ) 查看协同thread的当前状态
4、coroutine.resume( 协同变量 ) 让一个协同thread 从挂起状态转变成运行
5、coroutine.yield() 在一个运行的协同过程函数中调用,将运行的协同挂起。
10、MetaMethods(相当于c++类的operator重定义)
在lua中可以使用 setmetatable 给 table 设置重定义operator 的metatable 表,用 getmetatable 可以获取一个table的 metatable。
metatable 可以重定义的操作有
1、 加 + <----> __add
2、减 - <----> __sub
3、乘 * <----> __mul
4、除 \ <----> __div
5、负 - <----> __unm
6、幂 ^ <----> __pow
7、连接 ... <----> __conact
关系运算符metamethods
8、等于 == <----> __eq
9、小于 < <----> __lt
10、小于等于 <= <----> __le
没有 ~= 不等、 大于>、大于等于 >= 这三个操作符,因为lua会遇到他们时会为我们自动转换成上面三种去操作。
库定义的metamethods
11、tostring tostring <----> __tostring
12、缺失域 __index(获取缺失域的值) __newindex (给缺失域赋值)
一般情况下当访问 table 没有的域的时候是返回 nil 的。但是其实我们可以通过如下设置实现自定义回调。
1、给 table 的metatable的__index域指定一个遇到缺失域的时候的回调函数,函数原型是 function (table, key) functin (table, key, value) table 是缺失域的表,key 的缺失域的名字,value 是设置的值。
2、给 table 的metatable 的 __index 域指定一个 table,当遇到缺失的域时就到这个 指定的 table里面去找。
如果想对使用者隐藏metatable 可以将 metatable的 __metatable 域指定一个值,这样使用者getmetatable时返回这个值,使用者setmetatable时会出错。