《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程序
1 | 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 |
单行注释使用两个连字符开头;多行注释看着有点奇怪:
1 2 3 4 5 6 7 | -- 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()函数可以获取变量当前保存的值的类型:
1 2 3 4 5 6 7 8 9 10 11 12 | 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”。要使用多行字符串的话可以使用符号”[["和"]]”,就像使用多行注释一样:
1 2 3 4 5 6 7 8 | multilines = [[ <html> <title>page</title> <body>hello</body> </html> ]] print(multilines) |
但是如果字符串中含有”a[b[c]]”这样包含”]]”的字符串的话上面的方法就不起作用了。从5.1版本起,lua支持在第一个”[["的两个"["之间添加若干个"="作为起始标志,两个"]“之间拥有相同数量的”=”的”]]”作为对应的结束标志,像下面这样:
1 2 3 4 5 | 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可以是不同的类型:
1 2 3 4 5 | 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:
1 2 3 4 5 6 | 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"]:
1 2 3 4 | 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中只定义了赋值和判断是否相等两种操作。