- 算术操作符
- 关系操作符
- 逻辑操作符
- 字符串连接
- 优先级
- 表构造式
算术运算符
Lua支持常规的算术操作符,算术操作符用于实数。
+
二元加法
-
二元减法 取负
*
乘法
/
除法
^
指数求幂
%
求模取余
指数求幂
x = 4
print(x^0 .5) --计算平方根 2.0
x = 8
print(x^(1/3)) --计算立方根 2.0
print(x^(-1/3)) --计算立方根的倒数 0.5
求模取余
求模取余计算规则:a%b = a - floor(a/b)*b
,对于整数来说计算结果的符号永远与第二个参数相同,对于实数则由其他用途。
x = math.pi
print(x%1, x-x%1, x-x%0.01) -- 0.14159265358979 3.0 3.14
--[[
x%1 计算结果是x的小数部分
x-x%1 计算结果是x的整数部分
x-x%0.01 精确到小数点后两位
--]]
假设一辆车是否在旋转了一定角度后开始往回开,假如旋转角以角度给出。
local to_lerance = 10
function isTurnBack(angle)
angle = angle%360
return (math.abs(angle-180) < to_lerance)
end
print(isTurnBack(-180)) -- true
若以弧度代替角度
local to_lerance = 0.17
function isTurnBack(angle)
angle = angle%(math.pi*2)
return (math.abs(angle-math.pi)
关系运算符
<
大于
>
小于
>=
大于等于
<=
小于等于
~=
不等于
print(2>1 and 3>2) -- true
print(1>2 and 1<2) -- false
print(1<2 and 3) -- 3
print("521".."1314") -- 5211314
Lua提供的关系操作符包括< > <= >= == ~=
,其运算结果都是true
或false
。
==
用于相等性测试,~=
用于不等性测试,可应用于任意两个值。若两个值具有不同类型,Lua就认为他们是不相等的。否则,Lua会根据他们的类型来比较。注意nil
只与自身相等。
对于table
、userdata
、function
,Lua是做引用比较的。也就是说,只有当他们引用同一个对象时,才认为他们相等。
user = {};
user.age = 20;
user.weight = 80
person = {};
person.age = 20;
person.weight = 80
human = user
print( user == human, user ~= person) -- true true
- 只能对两个数字或字符串做大小比较
- Lua按字母次序(alphabetical order)比较字符串,具体的字母次序取决于对Lua的区域设置。
- 对两个不同类型的值比较时,要格外小心。
- 为避免类型不一致的比较,Lua会在遇到字符串和数字的大小比较时引发一个错误。
print("0"==0) -- false
print("2"<"15") -- false
print(2<"15") -- attempt to compare number with string
逻辑运算符
- 与
and
当两个表达式都为真时结果为真
若第一个表达式为真,第二个表达式为非布尔型的值,则输出此值。 - 或
or
当两个表达式其一为真,则结果为真。
若第一个表达式为false,第二个表达式为非布尔值,则输出此值。 - 非
not
取反运算,即布尔值取反。
不是false和nil的值都表示true
逻辑操作符有and or not
,与条件控制语句一样,所有逻辑操作符将false nil
视为假,其他都视为真。
- 对于
and
来说,如果第一个操作数为假,则返回第一个操作数,否则返回第二个操作数。
print(1 and 2) -- 2
print(nil and 1) -- nil
print(false and 1) -- false
- 对于
or
来说,如果第一个操作数为真,则返回第一个操作数,否则返回第二个操作数。
print(1 or 2) -- 1
print(nil or 1) -- 1
print(false or 1) -- 1
and
、or
都使用“短路求值(short-cut evaluation)”,也就是说,它们只会在需要时才去评估第二个操作数。短路求值可确保(type(v)=='table' and v.tag=='h1')
这样的表达式不会导致运行时错误。
常用的Lua习惯写法x = x or v
,它等价于if not x then x=v end
。
它可用在设置x的时候,即对x的求值结果为假时,将其设置为一个默认值。
常用Lua习惯写法(a and b) or c
,类似于C语言中的表达式a?b:c
,但前提是b不为假。
-- 选出数字x和y中的较大者
max = (x>y) and x or y
--[[
若x>y则and的第一个操作数为真,那么and运算结果就是第二个操作数x。
而x是一个永远为真的表达式,因为x是一个数字。
同理,or运算的结果就是第一个操作数x。
当x>y为假的时候,and表达式为假,因此or的结果就是第二个操作数y。
--]]
操作符not
永远返回的只是true
或false
print(not 0) -- false
print(not 1) -- false
print(not nil) -- true
print(not true) -- false
print(not false) -- true
字符串连接
..
连接符号为两个点,用于连接两个字符串。
Lua中连接两个字符串,可使用操作符..
,如果其中任意一个操作数是数字的话,Lua将会自动将数字转为字符串。
print("hello " .. "world") -- hello world
print(0 .. 1) -- 01
Lua中的字符串是不可变的值(immutable value),连接操作符只会创建一个新的字符串,而不会对原操作数做任何修改。
str = "hello "
print(str .. "world") -- hello world
print(str) -- hello
优先级
Lua操作符的优先级
^
not # -
* / %
+ -
..
< > <= >= == ~=
and
or
在二元操作符中,除了指数求幂^
和连接符..
是右结合外,其他操作符都是左结合(left associative)。
a+i < b/2+1
( a + i ) < ( ( b / 2 ) + 1 )
5 + x ^ 2 * 8
5 + ( ( x ^ 2 ) * 8 )
a
(x ^ 2)
x^y^z
x ^ ( y ^ z )
表构造式
表的构造,构造器是创建和初始化表的表达式,表是Lua特有的功能强大的数据类型,最简单的构造函数是{}
,用来创建空表。
local tbl = {}
表构造式(table constructor)用于创建和初始化table
的表达式,这是Lua特有的一种表达式,并且也是Lua中最有用、最通用的机制之一。
构造式可用于初始化数组
days = {"sunday", "monday", "tuesday", "wednesday", "thursday", "friday", "saturday"}
print(days[1], days[2], days[3], days[#days])
-- sunday monday tuesday saturday
Lua提供特殊语法用于创建记录风格的table
user = { name = "alice", age = 20 }
-- 等价代码
user = {}
user.name = "alice"
user.age = 20
无论采用哪种方式创建table
,都可以在table
创建后添加或删除其中的字段。
user = { name = "alice", age = 20, male = true }
user[1] = "admin"
print( user["name"], user[1] ) -- alice admin
user.name = nil
print(user["name"]) -- nil
所有的table
都可以构建成一样的,而构造式只是在table
的初始化时刻才发挥作用。
每当调用构造式时,会先创建一个新的table
,然后初始化它。这样,就能用table
构建链表结构list
。
list = nil
for line in io.lines() do
list = { next = list, value = line }
end
--[[
从标准输入读取每行内容,将每行按相反的次序存储到链表中。
链表中每个节点都有一个`table`,`table`中含有两个字段,`value`为每行的内容,`next`为指向下个节点的引用。
--]]
local l = list
while l do
print(l.value)
l = l.next
end
--[[
Lua程序很少使用链表,列表数据常用数组来实现。
--]]
将记录风格的初始化和列表风格的初始化混合在一个构造式中使用
polyline = {
color = "red",
thickness = 2,
npoint = 4,
{x = 0, y = 0},
{x = -10, y = 0}
}
print(polyline[2].x) --10
--[[
通过嵌套的构造式表示复杂的数据结构
--]]
两种风格的构造式各有限制
不能使用负数的索引,不能使用运算符作为记录的字段名。为了满足这些要求,Lua提供了更为通用的格式。格式允许在方括号之间,显式地用一个表达式来初始化索引值。
opnames = {
["+"] = "add",
["-"] = "sub",
["*"] = "mul",
["/"] = "div",
}
local str = "-"
print(opnames[str]) -- sub
无论是列表分隔的初始化,还是记录风格初始化,其实都是使用通用语法特例。
如果想要数组下标从0开始,可手工指定索引:
days = {
[0] = "Sunday",
"Monday",
"Tuesday",
"Wednesday",
"Thursday",
"Friday",
"Saturday"
}
不推荐数组下标从0开始,否则很多标准库不能使用。
某些情况如果以0作为数组的起始索引的话,不推荐在Lua中作为数组的其实索引。大多数内建函数都假设起始于索引1,若遇到以索引0开始的数组,它们就无法正确地处理了。
这种灵活性对于那些Lua table
的程序而言,它们无需将最后一个元素作为特例处理。
在构造函数“域分隔符”逗号,
可用分号;
替代,使用发呢好用来风格不同类型的表元素。
{
x = 10,
y = 10;
"username",
"password"
}