基础知识
Lua 使用 print() 函数输出字符串。
print("Hello, world")运行后你得到了结果。注意,它和其它 C-like 语言不一样,语句末尾不需要分号。
变量声明
Lua 是动态数据类型(弱类型)的语言,这意味着我们不能指定数据的基本类型。定义变量不需要关键字,直接写出变量名等于值即可。此变量默认是全局的,使用关键字 local 修饰才限制作用域在当前级别。
a = 114514
b = "你是一个一个一个......啊!"
local c = false;没有被声明的变量全部是 nil 类型的,值为 nil。
-- 输出 d,你会得到 nil
print(d)Lua 支持批量声明。
-- 这使得e和f都获得了指定值,但 g 仍然是 nil
e, f, g = 1919, "随便你戏弄"注释
Lua 注释比较独特,行注释使用 -- 开头,段注释使用 --[[ 和 --]] 包裹。取消段注释可以将段前标识改为 ---[[,这对于调试来说很方便。
-- print(1)
--- print(2)
--[[
print(3)
--]]
---[[
print(4)
--]]
-- 你最后只能得到 4 的输出基本数据类型
Lua 中有八大基本数据类型:
| 数据类型 | 名称 | 描述 |
|---|---|---|
| nil | 空 | 表示空,只有值 nil 属于该类,在条件表达式中相当于 false。 |
| boolean | 布尔 | 表示真假,只包含两个值:false 和 true。 |
| number | 数值 | 表示双精度类型的实浮点数。 |
| string | 字符串 | 表示字符序列。 |
| function | 函数 | 表示由 C 或 Lua 编写的函数。 |
| userdata | 用户数据 | 表示任意存储在变量中的 C 数据结构。 |
| thread | 线程 | 表示执行的独立线路,用于执行协同程序。 |
| table | 表 | Lua 中的表其实是一个关联数组(associative arrays),数组的索引可以是数字、字符串或表类型。表的创建是通过构造表达式来完成,最简单构造表达式是 {},用来创建一个空表。 |
数值和基本数值运算
Lua 中,数值(number)进制支持十进制和十六进制表达。
a = 114.514
b = 0x1919还可以使用科学计数法。
-- 2x10^8
c = 2e8运算方面除了常见的加减乘除,还支持幂运算和位运算。
-- 8
print(2 ^ 3)
print(1 << 3)字符串
Lua 中,字符串(string)用半角双引号对或单引号对包裹,涉及多行时,用 [[ 和 ]] 包裹。
a = "你是一个一个一个"
b = '吃得臭中臭,方撅人上人(喜'
c = [[你是内内个内内内个内个内内
内内个内内内个内个内内
内内个内内内个内个内内
阳光彩虹小白马]]单行字符串想要换行必须使用转义字符 \n,但多行字符串中既可直接换行,也可以使用转义字符。
拼接两个字符串使用 .. 而不是传统的加号。
d = "你是"
e = "内个"
g = d .. e -- g = "你是内个"数值和字符串之间可以借助函数互相转化。
h = "114514"
i = tonumber(h) -- tonumber() 函数将参数转化为数值
j = tostring(i) -- tostring() 函数将参数转化为字符串如果转换失败(如参数为 nil 或参数不符合类型要求),则函数返回值为 nil。
字符串 str 的长度为 #str。
k = "你是...你知道我要说什么"
print(#k) -- 33。其中每个中文字符占长度 3,亦表明 Lua 存储文本采用 Unicode函数
Lua 中,函数(function)的声明用关键字 function 表示,用 end 标识结束。
-- 与 JS 类似的表达办法,只不过没有花括号包围
function a(m, n)
print(m + n)
end
-- 另一种表达办法
b = function(m, n)
print(m + n)
end
-- 两者是完全相同的如果形参列表长度为
若函数不指定返回值,则函数总是为 nil。返回使用关键字 return。
-- 无返回值
function c(n)
r = n + 1
end
-- 有返回值
function d(n)
r = n + 1
return r
end
print(c(1), d(1)) -- nil 和 2返回值可以是一个变量,也可以是一个变量序列。
function e(m, n)
m = m + 1 -- Lua 中没有自增的概念
n = n + 1
return m, n
end
--我们可以使用序列来接收它
f, g = e(114514, 1919)表
Lua 中,表(table)与广义表类似。它的元素可以为任何数据类型,且一个表内可以混装不同的数据类型。
表的声明用花括号对,调用用方括号对。
a = {114514, "田所浩二", function() end, {}}
-- 表的索引从 1 开始计算
print(a[1]) -- 114514越界调用会得到 nil。
向表插入元素可直接赋值,也可使用既有函数:
b = {}
b[1] = 114514 -- 下标合法值取 [1, #b+1]
table.insert(b, 1919) -- 尾插元素
table.insert(b, 1, 810) -- 指定索引中插元素
-- #加表名可以获得数字下标的最大值
print(b[1], b[2], #b) -- 810、114514 和 3从表移除元素:
c = {114514, 1919, 810}
table.remove(c, 1) -- 指定索引移除元素
print(c[1]) -- 1919
print(table.remove(c, 1)) -- 1919。函数会返回移除掉的元素本身表除了可以使用数字下标,还可以使用字符串下标:
d = {
a = 114514, -- a 虽然本身是字符串,但并不需要加引号对
["b"] = "你是", -- 想加引号对,就得捆绑一个方括号对
c = "内个"
}
-- 调用可以沿用数字下标的形式,也可以用字符串下标独有的形式
print(d["a"]) -- 114514。这里写的 a 要用引号对包裹,注意
print(d.a) -- 114514。这个方式颇有面向对象的风味
print(#d) -- 0。该表内最大的数字下标就是 0
-- 可以向表中添加字符串下标的元素
d["motherfucker"] = "mf"
d.iloveyou = "ily"
print(d.motherfucker, d.iloveyou) -- mf 和 ily提问:在以上这个演示中,d["a"] 是 d[1] 吗?
d[1] 指的是表中第一个没有字符串下标的元素,在这里就是 nil。
Lua 中存在一个 _G 表,它存放了所有的全局变量。上面提到的 table.insert() 函数,就是放在 table 表内的,table 本身再处于 _G 中。我们可以验证 insert() 的类型:
print(_G["table"]["insert"]) -- function: addr
print(_G.table.remove) -- function: addr布尔型和判断语句
Lua 中,布尔(boolean)用于表示真(true)假(false)。nil 参与判断时视为假,其它所有数据类型视为真。
print(1 > 2) -- false
print(1 >= 1) -- true
print(1 == 1) -- true
print(1 ~= 1) -- false。~= 表示判断不等于与或非逻辑分别用关键字 and、or 和 not。涉及它们的最小判断单元的值,为代表真/假的操作数的值。
print(true and false) -- false
print(true or false) -- true
print(not true) -- false
print(1 and false) -- false。1 代表真,真并假为假,所以为 false
print(nil or "内个") -- "内个"。nil 代表假,"内个"代表真,假或真为真,所以为"内个"
print(not 0) -- false。0 为真,非真为假,所以为 false
print(nil and false) -- nil。两者都为假,假并假为假,返回第一个为假的操作数的值,所以为 nil提问:nil and "true" or "false" 的值是什么?
"false"。nil 先和字符串 "true" 并上,得到 nil;再和字符串 "false" 或上,得到字符串 "false"。
条件判断语句结构能够根据判断语句的真值执行不同的操作。其基本结构如下:
if sentence("判断语句 A") then
print("A 真值为真的操作")
elseif sentence("判断语句 B") then
print("B 真值为真的操作")
else
print("A、B 真值均为假的操作")
end循环
Lua 中,循环结构有三种,for、while 和 repeat 结构。
for 结构相较于 C 中的,被大幅精简。
-- 不指定步长,默认为 1
for i = 1, 10 do -- 这里的 i 是隐式 local 的,且具有只读属性
print(i) -- 1、2、3、4、5、6、7、8、9、10
end
-- 指定步长
for i = 1, 10, 2 do
print(i) -- 1、3、5、7、9
end
-- 指定负数步长
for i = 10, 1, -3 do
print(i) -- 10、7、4、1
end如果在 for 结构中尝试修改首行的局部变量,会被认为声明了一个新的全局变量。
while 结构和 repeat 结构相比起来更加简单。后者是先执行再判断,且条件属性从持续条件变为截止条件。
n = 114514
while n > 114510 do
print(n) -- 114514、114513、114512、114511
n = n - 1
end
n = 114514
repeat
print(n) -- 114514、114513、114512、114511
n = n - 1
until (n <= 114510)如果需要实现复杂功能,可以内置 if 结构加 break 语句。
更多
其实 Lua 作为一个关键字很少的脚本语言,基础知识并不足以满足现代开发。之后还有 IO、OOP 设计、协程等知识,如果你有兴趣,可以访问 Lua 的官方文档来自主学习。
精通 Lua 之后,不但可以做游戏脚本(最常见的用途),还可以涉足中小型程序开发。配合 C 的库,可以做到前后端通吃,节省你的大量时间。