# 引言
lua
作为一种简单、可扩展、可移植及高效的脚本语言,广泛地被用于网络游戏以及手机游戏中。写游戏常常需要跟 lua
打交道,还是做些笔记记下来,当做备忘,方便以后没事翻一翻
# 官方文档
在开始吹逼之前先放一下官方文档,毕竟官方的东西还是挺权威的 [http://www.lua.org/manual/][http://www.lua.org/manual/]
点击对应版本就可以看相关的 api
文档或者介绍了
# 一、类型与值
lua
中有 8 种基础类型如下表所示
数据类型 | 描述 |
---|---|
nil | 这个最简单,只有值 nil 属于该类,表示一个无效值 (在条件表达式中相当于 false ) |
boolean | 包含两个值: false 和 true |
number | 表示双精度类型的实浮点数 |
string | 字符串由一对双引号或单引号来表示 |
function | 由 C 或 Lua 编写的函数 |
userdata | 表示任意存储在变量中的 C 数据结构 |
thread | 表示执行的独立线路,用于执行协同程序 |
table | Lua 中的表 (table) 实是一个 "关联数组" (associative arrays) , 数组的索引可以是数字或者是字符串。在 Lua 里, table 的创建是通过 "构造表达式" 来完成,最简单构造表达式是 {} , 用来创建一个空表。 |
以下是 Lua
的变量的定义方式,区别在于未使用 local
关键字声明的变量将会是全局变量,而使用了 local
关键字声明的变量是局部变量,其余的 .lua
文件将不能顺利地访问。
local str = "hello wprld" | |
lcoal num = 10 | |
local flag = false | |
arg = "lua" | |
a = nil | |
b = 12 | |
print(c) --> nil |
# 二、表达式
# 算术运算符
Lua 支持的常规的运算符如下,假设 A = 10, B = 20
操作符 | 描述 | 实例 |
---|---|---|
+ | 加法 | A + B 输出结果 30 |
- | 减法 | A - B 输出结果 -10 |
* | 乘法 | A * B 输出结果 200 |
/ | 除法 | A / B 输出结果 2 |
% | 取余 | B % A 输出结果 0 |
^ | 乘幂 | A^2 输出结果 100 |
- | 负号 | -A 输出结果 -10 |
Hint: 这儿的 ^
是右结合运算符,即 2^3^2
结果是 512
而不是 64
# 关系运算符
下表列出了 Lua
语言中的常用关系运算符,同样设定 A = 10, B = 20
操作符 | 描述 | 实例 |
---|---|---|
== | 等于,检测两个值是否相等,相等返回 true , 否则返回 false | (A == B) 为 false |
~= | 不等于,检测两个值是否相等,相等返回 false , 否则返回 true | (A ~= B) 为 true |
> | 大于,如果左边的值大于右边的值,返回 true , 否则返回 false | (A > B) 为 false |
< | 小于,如果左边的值大于右边的值,返回 false , 否则返回 true | ( A < B) 为 true |
>= | 大于等于,如果左边的值大于等于右边的值,返回 true , 否则返回 false | (A >= B) 返回 false |
<= | 小于等于,如果左边的值小于等于右边的值,返回 true , 否则返回 false | (A <= B) 返回 true |
# 逻辑运算符
下表列出了 Lua
语言中的常用逻辑运算符,设定 A = true, B = false
操作符 | 描述 | 实例 |
---|---|---|
and | 逻辑与操作符。 若 A 为 false , 则返回 A , 否则返回 B | (A and B) 为 false |
or | 逻辑或操作符。 若 A 为 true , 则返回 A , 否则返回 B | (A or B) 为 true |
not | 逻辑非操作符。与逻辑运算结果相反,如果条件为 true , 逻辑非为 false | not (A and B) 为 true |
代码示例
print(4 and 5) | |
print(nil and 3) | |
print(false ans 13) | |
print(4 or 5) | |
print(false or 5) | |
-- output | |
5 | |
nil | |
false | |
4 | |
5 |
一些 Lua 的习惯性写法 -->
表示等价
a = a or b --> if not a then a = b end | |
(a and b) or c --> C 语言中 a ? b = c (当然使用前提为 b 不为假) |
# 其他运算符
即连接运算符与计算表或字符串长度的运算符如下表
操作符 | 描述 | 实例 |
---|---|---|
.. | 连接两个字符串 | a..b , 其中 a 为 "Hello " , b 为 "World" , 输出结果为 "Hello World" 。 |
# | 一元运算符,返回字符串或表的长度 | #"Hello" 返回 5 |
代码示例
print("hello " .. "world") | |
local num = 111 | |
print("num = " .. num) --> 在字符连接时 lua 会自动进行类型转换 | |
-- output | |
hello world | |
num = 111 |
# 运算符优先级
LUa 这个操作符的优先级由高到低如下表
oper | level |
---|---|
^ | 8 |
not - (unary) | 7 |
* / % | 6 |
+ - | 5 |
.. | 4 |
> < >= <= ~= == | 3 |
and | 2 |
or | 1 |
Hint: 除了 ^
和 ..
所有的二元运算符都是左连接的
代码示例
a + i < b / 2 + 1 --> (a + i) > ((b / 2) + 1) | |
5 + x^2 * 8 --> 5 + ((x^2) * 8) | |
a < y and y <>= z --> (a < y) and (y <= z) | |
-x^2 --> -(x^2) | |
x^y^z --> x^(y^z) |
# table 构造式
table
作为 lua
中唯一的数据结构,还是有点意思的,构造式就是用于创建和初始化 table
的表达式
最简单的就是一个空构造式 {}
按照风格划分, lua
的 table
构造式大致可以分为如下两种
- 记录风格:
a = {x=10, y=20}
代码等价于a = {} a.x = 10, a.y = 20
- 列表风格:
days = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"}
当然两种风格在实际的使用中经常混用,这个是完全没有问题的,记录风格的访问类似于 C 中结构体一样访问,比如 a.x
, 列表风格就和数组一样的访问形式
# 三、语句
# 赋值语句
赋值的基本含义就是指修改一个变量和 table
中的字段的值(在 lua
中没有经过复赋值的变量,默认值都是 nil
)
a = "hello" .. "world"
t.n = t.n + 1
此外, Lua
还支持 "多重赋值", 每个变量由 ,
分隔,如 a, b = 10, 2*x
在多重赋值中, Lua
会先对等号右边的所有元素求值,然后才执行赋值,并且赋值讲究 多弃少补 的原则,数量多余的舍弃,数量不足用 nil
赋值,比如下列语句都是合法的
a, b = b, a | |
a, b, c = 1, 2, 3, 4 | |
a, b, c = 1, 2 |
# 局部变量与块
相对与全局变量 lua
还提供了局部变量,用关键字 local
来创建,作用域仅限于申明他们的那个块,一个块可以是一个控制结构的执行体,或者是函数的执行体或者是一个程序块,这一点和其他的变成语言并没有什么不同。
当然尽可能的使用局部变量是一个好的编程习惯,可以有效避免将一些无用的变量名称引入全局环境,避免了搞乱全局环境。
# 控制结构
在 lua
中有以下几种控制结构,是编程语言这些都大同小异,下面就直接以代码例程形式给出了
if then else
先对 if
条件求值,根据测试结果执行 then
或者 else
部分
if a < 0 then a = 0 end | |
if a < b then return a else return b end | |
if line > MAXLINES then | |
showpage() | |
line = 0 | |
end | |
-- 当然多重嵌套的 if 也是可以的,lua 可以直接使用 elseif | |
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 | |
print("option is illegal") | |
end |
while
和其他语言一样, Lua
先测试 while
的条件,直到条件为假才终止,否则循环执行循环体之内的代码
local i = 1 | |
while a[i] do | |
print(a[i]) | |
i = i + 1 | |
end |
repeat
和它的名字一样,一条 repeat-until
语句重复执行循环体直到条件为真时结束
-- 打印输入的第一行不为空的内容 | |
repeat | |
line = io.read() | |
until line ~= "" | |
print(line) |
数字型for
& 泛型for
-- 数字型 | |
for i = 1, 10 do | |
print(i) | |
end | |
-- 泛型 for, 使用 pair 和 ipair 迭代遍历 table 中的内容 | |
local t1 = { | |
["str"] = {"str1", "str2", nil, "lua"}, | |
["num"] = {1, 2, 3, 4} | |
} | |
local t2 = { | |
[1] = {"str1", "str2", nil, "lua"}, | |
[2] = {1, 2, 3, 4} | |
} | |
print("------------------------") | |
for k, v in pairs(t1) do | |
print(k) | |
for k1, v1 in pairs(t1[k]) do | |
print(v1) | |
end | |
end | |
print("////////////////////////") | |
for k, v in pairs(t2) do | |
print(k) | |
for k1, v1 in pairs(t2[k]) do | |
print(v1) | |
end | |
end | |
print("=========================") | |
for i, v in ipairs(t1) do | |
print(i) | |
for k, v in ipairs(t1[i]) do | |
print(v) | |
end | |
end | |
print("+++++++++++++++++++++++++") | |
for i, v in ipairs(t2) do | |
print(i) | |
for k, v in ipairs(t2[i]) do | |
print(v) | |
end | |
end | |
-- output | |
------------------------ | |
num | |
1 | |
2 | |
3 | |
4 | |
str | |
str1 | |
str2 | |
lua | |
//////////////////////// | |
2 | |
1 | |
2 | |
3 | |
4 | |
1 | |
str1 | |
str2 | |
lua | |
========================= | |
+++++++++++++++++++++++++ | |
1 | |
str1 | |
str2 | |
2 | |
1 | |
2 | |
3 | |
4 | |
-- 可以看出 ipairs 对于 key 值为 string 的时候无法进行迭代,并且迭代过程中遇到 nil 即终止 | |
-- pairs 则不会有这种情况,pairs 遍历 table 所有元素,但并不一定有序 |
break
与 return
local i = 1 | |
while a[i] do | |
if a[i] == v then break end | |
i = i + 1 | |
end | |
function foo() | |
return -->> 错误语法 | |
do return end -->> ok |
# 结语
关于函数这些,lua 的库这些就在以后的博客中,在介绍吧,这篇博客就酱紫 Orz==
逃~~