01 开始
print("Hello World") --Hello World
Lua 中,换行不起任何作用。如果愿意,可以用分号分隔语句。
标识符和 C 一样,可以包含字母数字下划线,不能数字开头。尽量避免下划线跟着一串大写字母,Lua将其保留用作特殊用途。
P4 Lua 保留字
--这是行注释
--[[
这是块注释
--]]
--若想要重新启用块注释的代码
---[[ --在块注释的第一行加一个连字符即可
print(10)
--]]
全局变量
不需要声明,如果未初始化,结果是 nil
print(b) --nil
b = 10
print(b) --10
b = nil --如果要删除全局变量,将其赋值为nil
print(b) --nil
解释器
在运行脚本前,会用所有的命令行参数创建一个名为 arg 的 table,脚本名称在索引 0 上,第一个参数位于索引 1,脚本之前的选项参数位于负数索引上
02 类型与值
有八种基础类型:nil,boolean,number,string,userdata,function,thread,table
--type函数返回类型名称(返回值是string类型)
print(type("Hello")) --> string
print(type(type(42))) --> string
a = print --可以像操作别的值那样操作函数值
a(type(a)) --function
nil
是一种类型,只有一个值 nil,用于区别其他任何值。用于表示无效值的情况。
boolean
false 和 nil 视为假,其他所有值都是真,所以数字零和空字符串也是真
number
用于表示实数。lua 没有整数类型。
--可以使用科学计数法
print(5e+10) -->50000000000
string
Lua 的字符串是不可变的值,并且是自动内存管理机制所管理的对象,无需担心字符串的分配和释放。
--字面字符串用单双引号皆可
a = "a line"
b = 'another line'
--可以包含类似C的转义序列
c = "hi\nhello"
--可以用转义序列,通过数值指定字符
d = "hi\065hello"
print(d) -->hiAhello
--用双方括号界定字符串,不会解释转义序列
--回忽略第一个换行符
e = [[
first
second
]]
--如果字符串中出现]]
--可以在前后的双方括号之间加上数量相等的等号
--对块注释同样适用
f = [===[
first
a[b[]]
]===]
数字和字符串存在自动转换
print("10" + 1) -->11
print("10" * "2") -->20
-- ..是字符串连接符
print(10 .. 20) -->1020
--用函数显式转换
print(tonumber("100") * 30) -->3000
print(tostring(12.45) .. "hello") -->12.45hello
-- #是长度操作符
print(#(tostring(12.45) .. "hello")) -->10
table
实现了关联数组
a = {} --创建table
a[5] = 6
a["index"] = 100
print(a[5])
print(a["index"])
print(a.index) --语法糖,注意只有字符串索引可以这么用
--table是一种动态分配的对象,程序仅持有一个对它们的引用(指针)
b = a
b[5] = 1000
print(a[5]) -->1000
b = nil --只有a还在引用table
a = nil --没有对table的引用了
--此时Lua的垃圾收集器自动删除table,回收内存
如果要表示传统的数组,用整数 key 即可:
a = {}
for i = 1, 10 do
a[i] = i
end
for i = 1, 10 do
print(a[i])
end
--在Lua的习惯中,数组通常以1作为索引起始值
长度操作符的习惯用法:
print(a[#a]) --打印最后一个值
a[#a] = nil --删除最后一个值
a[#a+1] = 100 --把100加到列表末尾
对于包含空隙的数组,长度操作符会出问题
a = {}
a[1000] = 6;
print(#a) -->0
--可以使用table.maxn,返回table的最大正索引数
print(table.maxn(a)) -->1000
function
函数可以存储在变量中,可以通过参数传递给其他函数,可以作为函数的返回值。程序可以重新定义函数,或者删除某些函数。
userdata 和 thread
userdata 将任意 C 语言数据存储到 lua 变量中,只能进行赋值和相等性测试。
thread 详见第 9 章
03 表达式
算数操作符
二元:+ 加 - 减 * 乘 / 除 ^ 指数 % 取模
一元:- 负号
其中,取模的定义如下:
a % b == a - floor(a/b)*b
对于整数,计算结果的符号与第二个参数相同
对于实数,x%1 得到小数部分,x-x%0.01 是 x 精确到小数点后两位的结果
关系操作符
< > <= >= == ~=
全部返回 true 或者 false
注意 == 和 ~= 可以用于任意两个值。如果类型不同则不相等。nil 只和自身相等
对于 table,userdata,Lua 作引用比较
对于字符串和数字的大小比较会引发一个错误。
逻辑操作符
and or not
false 和 nil 视为假,其他都是真
对 and,如果第一个操作数为假,返回第一个操作数,否则返回第二个
对 or,如果第一个操作数为真,返回第一个操作数,否则返回第二个
and 和 or 都使用短路求值,类似 cpp
x = x or v
--等价于
if not x then x = v end
max = (x > y) and x or y
--等价于c中的
--max = x > y ? x : y
--前提是x不为假
not 永远只返回 true 或者false
字符串连接
… 操作符。因为 Lua 中字符串是不可变的,因此连接操作符只会创建一个新的字符串
优先级
P22
指数操作符和连接操作符是右结合的,其他都是左结合的。
table 构造式
--a[1] = "A",以此类推
a = {"A", "B", "C"}
for i = 1, #a do
print(a[i])
end
特殊的语法:
a = {x = 10, y = 20}
print(a.x == 10) -->true
每当 Lua 处理构造式,会先创建新的 table 然后初始化它。用 Lua 新建链表的代码:
list = nil
for line in io.lines() do
list = {next = list, value = line}
end
-- 输出
local l = list
while l do
print(l.value)
l = l.next
end
注意,真实的 Lua 程序很少使用链表。
更通用的格式如下:
opnames = {["+"] = "add", ["-"] = minus}
--可以嵌套
polyline = {color = "blue", {x = 5, y = 10}}
--等价于
polyline = {["color"] = "blue", {["x"] = 5, ["y"] = 10}}
在构造是中可以用分号代替逗号,功能没有不同,可以加强可读性