《programming in lua》第二版第 1-2 章。
运行环境
这里使用的 lua 版本是 5.1.4,操作系统是 debian 6.0,
到 lua 的官网下载源码包,因为是 ANSI C 写成的解析器,所以在各个平台上编译都很方便。编译之后会在源码目录里的 src 下生成两个可执行文件:lua 和 luac,其中 lua 用来解析脚本,luac 用来把脚本编译成二进制文件。在源码包里也带有一些例子,在 test 目录下。例如可以用下面的命令来运行 test 下的例子(假设当前目录为解压后的源码根目录):
./src/lua test/hello.lua
或者使用 luac 把脚本转换成二进制文件:
./src/luac test/hello.lua
默认的输出文件是 luac.out。接着可以使用 lua 来运行这个二进制文件:
./src/lua luac.out
得到的结果和直接运行脚本的结果一样,不过二进制文件的速度要快些。还有一种方法是直接执行 lua 语句:
lua -e "print(\"Hello, world.\")"
第一个 lua 程序
print("Hello, world!")
一个 lua 脚本或者在交互模式下的一行代码叫做块(chunk),块与块之间可以通过行来分隔,也可以通过分号来分隔,甚至写在同一行上的两条语句可以仅使用空格分隔。
变量命名规则和 c 差不多,都是数字,字母,下划线的组合,并且第一个字符不能是数字。保留的关键字有下面这些:
and break do else elseif
end false for function if
in local nil not or
repeat return then true until
while
单行注释使用两个连字符开头;多行注释看着有点奇怪:
-- the first program in lua
--[[
multiline comment
--]]
print("Hello, world.")
可以通过命令行向 lua 脚本传递参数。在 lua 脚本中有一个 arg 数组保存传递进来的参数。例如执行下面的命令:
lua script a b
arg 数组的各个值如下:
arg[-1] = lua
arg[0] = script
arg[1] = a
arg[2] = b
类型
lua 是一种动态类型的语言,变量在使用前不需要声明,初始值为 nil。在 lua 中变量是没有类型的,只有变量中保存的值才有类型。lua 中有 8 种基本类型:nil,boolean,number,string,userdata,function,thread,table。通过 type() 函数可以获取变量当前保存的值的类型:
print(type(a)) -- nil
a = 10
print(type(a)) -- number
a = "abc"
print(type(a)) -- string
a = print
print(type(a)) -- function
print(type(type(a))) -- string
无论 a 是什么类型,最后的语句总是输出 string
,因为 type() 的返回值是 string 类型。
boolean 只有两种取值:true 和 false。除了 nil 和 false 的值为 false 之外,其它的值均为 true(0 和空字符串也为真,这点与 c 不一样)。
number 类型代表所有实数,不区分整型和浮点型(单精度或双精度)。number 型也可以采用科学计数法,如 2.5e12 等。
string 类型可以使用单引号或双引号来界定,如果字符串中有相同的引号可以使用反斜杠转义(例如 a = "abc\"d"
这样的),或者使用不同于字符串内引号的另一种引号(例如 a = 'abc"d'
或者 a = "abc'd"
)。lua 也有类似 c 中的一些特殊转义字符,如换行 \n
,制表 \t
等。如果反斜杠后跟数值表示某个字符的 ascii 值,例如“print("\99")”会打印字符“c”。要使用多行字符串的话可以使用符号 [[
和 ]]
,就像使用多行注释一样:
multilines = [[
<html>
<title>page</title>
<body>hello</body>
</html>
]]
print(multilines)
但是如果字符串中含有 a[b[c]]
这样包含 ]]
的字符串的话上面的方法就不起作用了。从 5.1 版本起,lua 支持在第一个 [[
的两个 [
之间添加若干个 =
作为起始标志,两个 ]
之间拥有相同数量的 =
的 ]]
作为对应的结束标志,像下面这样:
multilines = [=[
a[b[c]]
]=]
print(multilines)
[[
和 ]]
之间的 =
可以为任意数量,但数量一定要相等。同样的语法也可以用在注释中(即在 --[[
的两个 [
中添加 =
,同样结束的位置 --]]
的两个 ]
中也要有相同数量的 =
)。
lua 提供了 string 到 number 的自动转换,例如 print("10" + 1)
输出 11
,但是 print("hello" + 1)
会报错,原因是不能将字符串 hello
转换成数值。字符串连接符 ..
可以把数值转换成字符串,例如 print(10 .. 20)
会输出 1020
(注意 ..
两边有空格)。总的来说,上面这些隐式转换都不是好习惯,如果要进行转换最好使用函数显式转换,例如转换成数值可以使用函数 tonumber(),转换成 string 可以使用 tostring() 等。
在 lua5.1 之后可以使用 #
来获取 string 的长度,例如 print(#"hello")
的输出是 5
。
table 是 lua 中唯一的数据结构,是一种关联数组,而且 table 中的 key 可以是不同的类型:
a = {} -- create a table and store its reference in 'a'
a["x"] = 10
print(a["x"]) -- 10
a[20] = "k"
print(a[20]) -- k
变量 a 只是保存对 table 的一个引用,如果把 a 赋值给另一个变量 b,那么 a 和 b 指向的是同一个 table:
a = {} -- create a table and store its reference in 'a'
a["x"] = 10
b = a
print(b["x"]) -- 10
b["x"] = 5
print(a["x"]) -- 5
通过把 nil 赋给变量可以删除一个变量所指向的内容,lua 的 garbage collector 会将无用的内存收集起来重新投入使用。
另外一种访问 table 元素的方法有点像访问结构体成员的“.”操作符,也即 a.key
相当于a["key"]
:
y = "x"
a.y = 10 -- a["x"] = 10
print(a.x) -- print(a["x"])
print(a.y) -- nil
.
后面的是 key 而不是指向 key 的变量的名称。
function 可以作为参数传递,也可以作为返回值。
userdata 是用户自定义的 c 语言数据类型,可以存储在 lua 变量中,lua 中只定义了赋值和判断是否相等两种操作。
用撸啊干什么活儿啊???
学着玩的…
魔兽插件用的就是这个语言…求写插件