此第一版是为 Lua 5.0 编写。虽然对后续版本仍然非常相关,但存在一些差异。
第四版针对 Lua 5.3,可在 亚马逊 和其他书店购买。
通过购买本书,您还可以帮助 支持 Lua 项目。
编程 in Lua | ||
第一部分。语言 第 2 章。类型和值 |
表类型实现关联数组。关联数组是一种数组,它不仅可以用数字索引,还可以用字符串或语言的任何其他值(nil 除外)索引。此外,表没有固定大小;您可以根据需要动态地向表中添加任意多个元素。表是 Lua 中的主要(事实上是唯一的)数据结构化机制,而且非常强大。我们使用表以简单、统一且高效的方式表示普通数组、符号表、集合、记录、队列和其他数据结构。Lua 也使用表来表示包。当我们编写 io.read
时,我们的意思是“io
包中的 read
条目”。对于 Lua,这意味着“使用字符串 "read"
作为键对表 io
进行索引”。
Lua 中的表既不是值也不是变量;它们是对象。如果您熟悉 Java 或 Scheme 中的数组,那么您对我们的意思会有一个公平的了解。但是,如果您对数组的理解来自 C 或 Pascal,您必须稍微开阔一下思路。您可以将表视为一个动态分配的对象;您的程序仅操作它们的引用(或指针)。在幕后没有隐藏的副本或新表的创建。此外,您不必在 Lua 中声明一个表;事实上,没有办法声明一个表。您可以通过构造函数表达式创建表,其最简单的形式写为 {}
a = {} -- create a table and store its reference in `a' k = "x" a[k] = 10 -- new entry, with key="x" and value=10 a[20] = "great" -- new entry, with key=20 and value="great" print(a["x"]) --> 10 k = 20 print(a[k]) --> "great" a["x"] = a["x"] + 1 -- increments entry "x" print(a["x"]) --> 11表始终是匿名的。持有表的变量与表本身之间没有固定的关系
a = {} a["x"] = 10 b = a -- `b' refers to the same table as `a' print(b["x"]) --> 10 b["x"] = 20 print(a["x"]) --> 20 a = nil -- now only `b' still refers to the table b = nil -- now there are no references left to the table当程序不再引用某个表时,Lua 内存管理最终会删除该表并重新利用其内存。
每个表都可以存储具有不同类型索引的值,并且会根据需要容纳新条目而增长
a = {} -- empty table -- create 1000 new entries for i=1,1000 do a[i] = i*2 end print(a[9]) --> 18 a["x"] = 10 print(a["x"]) --> 10 print(a["y"]) --> nil请注意最后一行:与全局变量一样,如果表字段未初始化,则其值为 nil。同样与全局变量一样,您可以将 nil 分配给表字段以将其删除。这不是巧合:Lua 将全局变量存储在普通表中。有关此主题的更多信息,请参见 第 14 章。
要表示记录,您可以使用字段名称作为索引。Lua 通过提供 a.name
作为 a["name"]
的语法糖来支持此表示。因此,我们可以以更简洁的方式编写上一个示例的最后几行,如下所示
a.x = 10 -- same as a["x"] = 10 print(a.x) -- same as print(a["x"]) print(a.y) -- same as print(a["y"])对于 Lua,这两种形式是等效的,并且可以自由混合使用;但对于人类读者,每种形式可能表示不同的意图。
初学者常犯的一个错误是将 a.x
与 a[x]
混淆。第一种形式表示 a["x"]
,即由字符串 "x"
索引的表。第二种形式是按变量 x
的值索引的表。请看区别
a = {} x = "y" a[x] = 10 -- put 10 in field "y" print(a[x]) --> 10 -- value of field "y" print(a.x) --> nil -- value of field "x" (undefined) print(a.y) --> 10 -- value of field "y"
要表示常规数组,您只需使用具有整数键的表。没有办法声明其大小;您只需初始化所需的元素
-- read 10 lines storing them in a table a = {} for i=1,10 do a[i] = io.read() end当您遍历数组的元素时,第一个未初始化的索引将导致 nil;您可以使用此值作为哨兵来表示数组的结尾。例如,您可以使用以下代码打印上一个示例中读取的行
-- print the lines for i,line in ipairs(a) do print(line) endLua 基本库提供了
ipairs
,这是一个方便的函数,允许您遍历数组的元素,遵循数组在其第一个 nil 元素处结束的约定。
由于你可以使用任何值对表进行索引,因此你可以从你喜欢的任意数字开始数组的索引。然而,在 Lua 中通常从一(而不是像在 C 中那样从零)开始数组,并且标准库坚持此惯例。
由于我们可以使用任何类型对表进行索引,因此在对表进行索引时,我们遇到了与相等性中出现的相同细微差别。虽然我们可以使用数字 0
和字符串 "0"
对表进行索引,但这两个值(根据相等性)是不同的,因此表示表中的不同位置。同样,字符串 "+1"
、"01"
和 "1"
都表示不同的位置。当对索引的实际类型有疑问时,请使用显式转换以确保
i = 10; j = "10"; k = "+10" a = {} a[i] = "one value" a[j] = "another value" a[k] = "yet another value" print(a[j]) --> another value print(a[k]) --> yet another value print(a[tonumber(j)]) --> one value print(a[tonumber(k)]) --> one value如果你不注意这一点,你可能会在你的程序中引入细微的错误。
版权所有 © 2003–2004 Roberto Ierusalimschy。保留所有权利。 |