Chapter 3: Expressions
3.1 Arithmetic Operators
x^0.5 -- 计算x 的平方根
a % b == a - floor(a/b)*b
x%1 -- 计算x 的小数部分
x-x%1 -- 计算x 的整数部分
x-x%0.01 -- x 保留两位小数
x = math.pi
print(x - x%0.01) --> 3.14
关于度和弧度的两个函数
local tolerance = 10
function isturnback (angle)
angle = angle % 360
return (math.abs(angle - 180) < tolerance)
end
print(isturnback(-180)) --> true
local tolerance = 0.17
function isturnback (angle)
angle = angle % (2*math.pi)
return (math.abs(angle - math.pi) < tolerance)
end
3.2 Relational Operators
关系运算符
< > <= >= == ~=
这些运算符都返回true 或 false.
注意:~= 表示不等于
string 按字典序比较
3.3 Logical Operators
逻辑操作符
and, or, not.
and 操作符返回第一个参数或第二个参数,由整个表达式的真假决定。
print(4 and 5) --> 5 -- and 表达式为真,返回第二个参数
print(nil and 13) --> nil -- and 表达式为假,返回第一个参数
print(false and 13) --> false
or 操作符返回第一个参数或第二个参数,由整个表达式的真假决定。
print(4 or 5) --> 4 -- or 表达式为真,返回第一个参数
print(false or 5) --> 5 -- or 表达式为假,返回第二个参数
and, or 都有短路功能。
Lua 中的习惯用法
x=x or v -- 如果x 没有值,赋默认值v 给x
等价于 if not x then x = v end
(a and b) or c -- 或 a and b or c ,因为and 优先级高于or
等价于C 语言的 a?b:c
max = (x > y) and x or y -- 取两个数的较大值
not 总是返回true 或false
print(not nil) --> true
print(not false) --> true
print(not 0) --> false
print(not not nil) --> false
3.4 Concatenation
连接两个串的运算符 ..
如果 .. 的参数存在数字,则lua 将其自动转成string
print("Hello " .. "World") --> Hello World
print(0 .. 1) --> 01
注意string 是不可改变量,串连接运算符总是创建一个新串
a = "Hello"
print(a .. " World") --> Hello World
print(a) --> Hello
3.5 Precedence 优先级
^
not # - (unary)
* / %
+ -
..
< > <= >= ~= ==
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)
3.6 Table Constructors
构造空表
{}
构造string 表
days = {"Sunday", "Monday", "Tuesday", "Wednesday",
"Thursday", "Friday", "Saturday"}
print(days[4]) --> Wednesday
注意:表的第一个有效索引是1
构造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" -- 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"
创建一个链表,逆序存储标准输入中的每一行
list = nil
for line in io.lines() do
list = {next=list, value=line}
end
对list 的每次赋值都创建一个新表
打印list 的每个值
local l = list
while l do
print(l.value)
l = l.next
end
上面的代码很少用于实际程序中,list 用数组来实现更好,参见11 章。
polyline = {color="blue", thickness=2, npoints=4,
{x=0, y=0}, -- 索引是1
{x=-10, y=0}, -- 索引是2
{x=-10, y=1},
{x=0, y=1}
}
print(polyline[2].x) --> -10
print(polyline[4].y) --> 1
构造具有特殊索引的表
创建具有负索引、0 索引,或非标识符索引的表
非标识符索引:
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"}
这种语法虽然笨重,但是更灵活,
0 索引:
days = {[0]="Sunday", "Monday", "Tuesday", "Wednesday",
"Thursday", "Friday", "Saturday"}
Sunday 的索引是0,这个0 索引不影响其它域,"Monday" 的引索是1
注意:不建议在lua 中使用0 索引。
大多数内置函数假定数组索引从0 开始,因此它们不能正确处理这一状况。
表的最后一项后面的逗号是可选的
a = {[1]="red", [2]="green", [3]="blue",}
表的构造器里面可以用分号代替逗号
{x=10, y=45; "one", "two", "three"} -- 分号用来区分list part 和record part
通常用分号来区分表中的不同section