# 引言

lua 作为一种简单、可扩展、可移植及高效的脚本语言,广泛地被用于网络游戏以及手机游戏中。写游戏常常需要跟 lua 打交道,还是做些笔记记下来,当做备忘,方便以后没事翻一翻

# 官方文档

在开始吹逼之前先放一下官方文档,毕竟官方的东西还是挺权威的 [http://www.lua.org/manual/][http://www.lua.org/manual/]

点击对应版本就可以看相关的 api 文档或者介绍了

# 一、类型与值

lua 中有 8 种基础类型如下表所示

数据类型描述
nil这个最简单,只有值 nil 属于该类,表示一个无效值 (在条件表达式中相当于 false )
boolean包含两个值: falsetrue
number表示双精度类型的实浮点数
string字符串由一对双引号或单引号来表示
functionCLua 编写的函数
userdata表示任意存储在变量中的 C 数据结构
thread表示执行的独立线路,用于执行协同程序
tableLua 中的表 (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逻辑与操作符。 若 Afalse , 则返回 A , 否则返回 B(A and B)false
or逻辑或操作符。 若 Atrue , 则返回 A , 否则返回 B(A or B)true
not逻辑非操作符。与逻辑运算结果相反,如果条件为 true , 逻辑非为 falsenot (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 这个操作符的优先级由高到低如下表

operlevel
^8
not - (unary)7
* / %6
+ -5
..4
> < >= <= ~= ==3
and2
or1

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 的表达式

最简单的就是一个空构造式 {}

按照风格划分, luatable 构造式大致可以分为如下两种

  • 记录风格: 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 所有元素,但并不一定有序

breakreturn

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== 逃~~

更新于 阅读次数