在Lua中,表达式包括:数值常量、字符串字面值、变量、单目和双目运算符,函数调用,也包括一些非传统的函数定义和表结构。
1.算术运算符
Lua支持常规的算术运算符:'+', '-', '*', '/', '^', '%', '-'(负)。所有这些运算符都对实数起作用。举个例子,x^0.5, 计算x的平方根, x^(-1/3),计算x的立方根的反数。
在Lua中,'%'运算符定义规则如下:
a%b == a - floor(a/b)*b a%b得到的值一定是正的,lua用%进行运算,余数非零,就是非负。所以取余想得到正常的结果用math.fmod(被除数,除数)
对整型参数来说,它表示常规的意义,结果跟第二个参数b符号相同。
对实数来说,它有一些额外的用途。例如,x%1 表示x的小数部分,x-x%1 表示x的整数部分。类似的,x-x%0.01 将x精确到小数点后2位。
2.关系操作符
Lua提供了如下关系操作符:
< > <= >= == ~=
所有这些操作符产生的结果都是true或者false
'=='检查是否相等,'~='检查是否不等。这两个操作符可以作用于任意的两个值。如果要比较的两个值是不同的类型,那么Lua认为它们是不等的。否则,Lua根据它们的类型来比较它们是否相等。特例,nil只等于它本身。(先比较类型,然后再根据类型比较值)
Lua根据引用来比较table, userdata, function,也就是说,只有二者是同一个对象的时候,它们才相等。例如:
- a = {}; a.x = 1; a.y = 0
- b = {}; b.x = 1; b.y = 0
- c = a
我们把<, >, <=, >=称为order operator。
order operator只能应用于数值和字符串。Lua根据字母表顺序来比较字符串的大小,字母表的顺序由本地设置决定。非数值和字符串的值只能比较相等或者不相等,不能用于order operator。
当比较两个不同类型的值时,一定要小心:记住"0"和0是不同的。除此以外,2<15显然是true的,但是"2"<"15"是false的(根据字母表顺序比较)。为了避免不一致的结果,当你将string和number混合使用到order operator时,例如 2<"15",Lua会产生一个runtime error。
3.逻辑运算符
逻辑运算符有:and, or, not。跟控制结构(if,while等)类似,所有的逻辑操作符把false和nil认为是false,其他的任意值都为true。
and:如果第一个参数为false,返回第一个参数,否则返回第二个参数。
or :如果第一个参数为false,返回第二个参数,否则返回第一个参数。
- print(4 and 5) ----> 5
- print(nil and 13) ----> nil
- print(false and 13) ----> false
- print(4 or 5) ----> 4
- print(false or 5) ----> 5
'and'和'or'都是用short-cut计算方式,也即是说,只有在有需要的时候,才会去计算第二个参数的值。这样保证了类似(type(v)=="table" and v.tag=="h1")这样的表达式不会产生run-time error。(当v不是table类型时,Lua不会去计算v.tag的值)。
"短路求值",又称最小求值,是一种逻辑运算符的求值策略。有当第一个运算值无法确定逻辑运算的结果,才去对第二个运算数进行求值。
有用的Lua表达式:x = x or v,等价于:
if not x then x = v end
(加上x没有被赋值为false),如果x没有被设置,那么给它个默认值v。
另一个有用的Lua表达式:a and b or c,等价于C表达式 a ? b : c,(假设b不为false)。例如,我们可以用下面的语句来得到x和y的最大值。
max = (x >y) and x or y
当 x>y,第一个and表达式结果为第二个参数x,x总是true(因为x为一个数值),那么or表达式的结果为x or y,结果为x。
当 x<y,第一个and表达式的结果为false,那么or表达式的值就为false or y,结果为y。
'not'操作符总是返回true或者false
- print(not nil) --> true
- print(not false) --> true
- print(not 0) --> false
- print(not not nil) --> false
4.连接操作符
Lua用'..'(两个点)来表示string连接符。如果它的任一个操作数为数字,Lua会把它转为string。
- print("Hello " .. "World") --> Hello World
- print(0 .. 1) --> 01
- a = "Hello"
- print(a .. " World") --> Hello World
- print(a) --> Hello
5.优先级
Lua中的操作符优先级,如下表所示,从高到低
- ^
- not # -(单目)
- * / %
- + -
- ..
- < > <= >= ~= ==
- and
- or
- a+i < b/2+1 <--> (a+i) < ((b/2)+1)
- 5+x^2*8 <--> 5+((x^2)*8)
- a<y and y<=z <--> (a<y) and (y<=z)
- -x^2 <--> -(x^2)
- x^y^z <--> x^(y^z)
6.表构造函数
构造函数是一个用来初始化表(table)的表达式。它是Lua的一个独特特性和很强大的功能之一。
最简单的构造函数是空构造函数,{},创建一个空table。构造函数也可以初始化数组,例如:
- days = {"Sunday", "Monday", "Tuesday", "Wednesday",
- "Thursday", "Friday", "Saturday"}
将day[1]初始化为"Sunday", day[2]为"Monday",注意,index是从1开始 。
- print(day[4]) --> Wednesday
- 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 filed" -- add key 1 to table 'w'
- x.f = w -- add key 'f' to table 'x'
- print(w["x"]) --> 0
- print(w[1]) --> another field
- print(x.f[1]) --> another field
- w.x = nil -- remove field 'x'
Lua每次使用构造函数,都会创建并初始化一个新的table。因此,我们可以用table来实现一个list:
- 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
以上两段代码的示例:
我们可在一个构造函数中同时使用record-style和list_style的初始化方式:
- polyline = {color="blue", thickness=2, npoints=4,
- {x=0, y=0},
- {x=-10, y=0},
- {x=-10, y=1},
- {x=0, y=1}
- }
- print(polyline[2].x) --> -10 --此处要注意index 1是从哪里开始的,下面的示例may be helpful
- print(polyline[4].y) --> 1
因此,Lua提供了一种更通用的格式。在这个格式中,我们显式的写出每一个[index]。
- 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]) --> ---
这个规则有点麻烦,但是更方便灵活:record-style和list_style是这个通用格式的两个特例而已。
- {x=0, y=0} <==> {["x"]=0, ["y"]=0}
- {"r", "g", "b"} <==> {[1]="r", [2]="g", [3]="b"}
有时候,你想要你的array的index从0开始(Lua默认从1开始),用下面的方式就可以了:
- days = {[0]="Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"}
现在,第一个值"Sunday", index为0 。它不会影响其他的field;"Monday"的index为1,因为它是构造函数中的第一个list值;其他的跟随。尽管实现很便利,但是不推荐这样用。Lua的很多内置函数都假设array的index从1开始,如果一个array从0开始,可能会在处理上有问题。
在最后一个元素后面,可以加逗号','。这个末尾的逗号','是可选的,但都是合法的:
- a = {[1]="red", [2]="green", [3]="blue",}
通过这个便利性,程序在生成Lua table的时候不需要对最后一个元素做特殊处理。
最后,我们可以使用分号';'来代替逗号',',你可以在用';'来分割table中的不同属性的部分,例如:
- {x=10, y=45; "one", "two", "three"}