表构造器( Table Constructor
)是用来创建和初始化表的表达式,也是 Lua
语言中独有的也是最有用、最灵活的机制之一。
列表式
正如我们此前已经提到的,最简单的构造器是空构造器{}
。表构造器也可以被用来初始化表。例如:
days = { "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" } print(days[4]) -- > Wednesday
记录式
Lua
语言还提供了一种初始化记录式(record-like)表的特殊语法:
a = {x = 10, y = 20}
上述代码等价于:
a = {} a.x = 10 a.y = 20
不过,在第一种写法中,由于能够提前判断表的大小,所以运行速度更快。
无论使用那种方式创建表,都可以随时增加或删除表元素。
w = {x = 0, y = 0, label = "console"} x = {math.sin(0), math.sin(1), math.sin(2)} w[1] = "another field" -- 把键1增加到表'w'中 x.f = w -- 把键"f"增加到表'x'中 print(w["x"]) --> 0 print(w[1]) --> another field print(x.f[1]) --> another field w.x = nil --> 删除字段'x'
不错,正如此前所提到的,使用合适的构造器来创建表会更加高效和易读。
在同一个构造器中,可以混用记录式(record-style)和列表式(list-style)写法:
polyline = { color = "blue", thickness = 2, npoints = 4, {x = 0, y = 0}, -- polyline[1] {x = -10, y = 0}, -- polyline[2] {x = -10, y = 1}, -- polyline[3] {x = 0, y = 1} -- polyline[4] }
上述的示例也同时展示了如何创建嵌套表(和构造器)以表达更加复杂的数据结构。每一个元素 polyline[i]
都代表一条记录的表:
print(polyline[2].x) --> -10 print(polyline[4].y) --> 1
括号式
不过,这两种构造器都有各自的局限。例如:使用这两种构造器时,不能使用负数索引初始化表元素,也不能使用不符合规范的标识符作为索引。对于这类需求,可以使用另一种更加通用的构造器,即通过方括号括起来的表达式显示地指定每一个索引:
opnames = {["+"] = "add", ["-"] = "sub", ["*"] = "mul", ["/"] = "div"} i = 20 s = "-" a = {[i + 0] = s, [i + 1] = s .. s, [i + 2] = s .. s .. s} print(opnames[s]) --> sub print(a[22]) --> ---
这种构造器虽然冗长,但却非常灵活,不管是记录式构造器还是列表式构造器均是其特殊形式。例如,下面的集中表达式就相互等价
{x = 0, y = 0} <--> {["x"] = 0, ["y"] = 0} {"r", "g", "b"} <--> {[1] = "r", [2] = "g", [3] = "b"}
在最后一个元素后总是可以紧跟一个逗号。虽然总是有效,但是否加最后一个逗号是可选的:
a = {[1] = "red", [2] = "green", [3] = "blue",}
这种灵活性似的开发人员在编写表构造器时不需要对最后一个元素进行特殊处理。
最后,表构造器中的逗号也可以使用分号代替,这主要是为了兼容 Lua
语言的旧版本,目前基本不会被用到。