一、表达式
不同于传统的是:Lua表达式中可以包括函数定义和table构造式。
1、算数操作符
Lua支持常规的算术操作符有:二元的+(加法)、-(减法)、*(乘法)、/(除法)、^(指数)、%(取模),一元的-(负号)。所有这些操作符都可用于实数。
计算结果的符号永远与第二个参数相同。
2、关系操作符
Lua提供了以下关系操作符:<、>、<=、>=、==、~=。所有这些操作符的运算结果都是true或false。
操作符==用于相等性测试,操作符~=用于不等性测试。这两个操作符可以应用于任意两个值。如果两个值具有不同类型,则认为它们不相等,否则,Lua会根据它们的类型来比较两者。需要注意的是:nil只与其自身相等。
对于table、userdata和函数,Lua是作引用比较的,即只有当它们引用同一个对象时,才认为它们相等。
3、逻辑操作符
逻辑操作符有and、or和not。所有逻辑操作符将false和nil视为假,而将其它的任何东西视为真。
需要注意的是,Lua逻辑操作符的结果遵循以下规则:
(1)对于and操作符来说,如果它的第一个操作数为假,就返回第一个操作数,否则返回第二个操作数。
(2)对于or操作符来说,如果它的第一个操作数为真,就返回第一个操作数,否则返回第二个操作数。
(3)操作符not永远只返回true或者false。
print(4 and 5) -->5
print(nil and 13) -->nil
print(4 or 5) -->4
print(false or 5) -->5
print(not nil) -->true
print(not 0) -->false
4、字符串连接
Lua连接两个字符串可以使用操作符..(两个点),如果其任意一个操作数是数字的话,Lua会将这个数字转换成一个字符串:
print("hello" .. "world") -->hello world
print(0 .. 1) -->01
需要注意的是:Lua中的字符串是不可变的值(immutable value),连接操作符只会创建一个新字符串,而不会对其原操作数进行任何修改:
a = "hello"
print(a .. "world") -->hello world
print(a) -->hello
5、优先级
不要依赖于某种语言的优先级,而是用括号来保证运算次序,这放在任何语言都合适,因此,在此不给同学们任何接触优先级的机会
。
6、table构造式
构造式是用于创建和初始化table的表达式,这是Lua特有的一种表达式,并且也是Lua中最有用、最通用的机制之一。
empty = {} --空table
days = {"Sunday", "Monday", "Tuesday", "Wedensday", "Thursday", "Friday", "Saturday"}
a = {x=10, y=20}
二、语句
Lua支持的常规语句基本与C语言差不多,包括赋值、控制结构和过程调用,但是Lua还支持多重赋值(multiple assignment)和局部变量声明。
1、赋值
Lua的普通赋值通C语言,这里主要介绍下多重赋值,即一次将多个值分别赋给多个变量,每个值或每个变量之间以逗号分隔,例如:
a, b = 10, 2 --a=10, b=2
在多重赋值中,Lua先对等号右边的所有元素求值,然后才执行赋值。这样便可以用一句多重赋值来交换两个变量的值了:
x, y = y, x --交换x与y
Lua总是会将等号右边值的个数调整到与左边变量的个数相一致,若值的个数少于变量的个数,那么多余的变量会被赋值为nil,若值的个数更多的话,那么多余的值会被丢弃:
a, b, c = 0, 1 --a=0, b=1, c=nil
a, b = a+1, b+1, b+2 --a=1, b=2, b+2被丢弃
一般情况下,赋值不会用到多重赋值,因为这并不比多条单一变量赋值语句更快。多重赋值一般应用于交换变量值或者函数返回多个值时。
2、局部变量与块
Lua通过local语句来创建局部变量:
j = 10 --全局变量
local i = 1 --局部变量
与全局变量不同的是,局部变量作用域限于声明的块内,一个块(block)是一个控制结构的执行体或者一个函数的执行体或者一个程序块(chunk)。
在交互模式中,每行输入内容自成一块,回车后会马上执行,这样下一行就不能用前一行的变量了,因为是local,为了解决此问题,引入了do-end,每当输入do时,Lua不会单独执行其后面的每行内容直至遇到一个相应的end时,才会执行整个块的内容。
尽量使用局部变量可以避免将一些无用的名称引入全局环境(global environment),避免搞乱了全局环境。访问局部变量比全局变量快,且局部变量在其作用域结束时,会被垃圾收集器回收并释放其值。
3、控制结构
Lua提供用于条件执行的if,用于迭代的while、repeat和for。所有控制结构都有一个显示的终止符:if、for和while以end结尾,repeat以until结尾。
(1)if
if 条件 then 语句 end
if 条件 then 语句 elseif 条件 then 语句 end
需要注意的是:Lua不支持switch语句,而用if-else-if来替代。
(2)while
while 条件 do 语句 end
(3)repeat
repeat同C语言中的do ... while,都是先执行循环体直到条件为真时结束:
repeat 语句 until 条件
Lua中,循环体中局部变量的作用域包括条件测试。
(4)数字型for
for语句有两种形式:数字型for(numeric for)和泛型for(generic for)。
数字型for语法如下:
for var=exp1, exp2, exp3 do
<执行体>
end
var从exp1变化到exp2,每次变化都以exp3作为步长递增var,并执行一次“执行体”。exp3是可选的,若不指定则Lua将步长默认为1:
for i=1, f(x) do print(i) end
for i=10, 1, -1 do print(i) end
对于for循环需要注意:
(A)for的3个表达式是在循环开始前一次性求值的,如:f(x)只会执行一次。
(B)控制变量会被自动声明为for语句的局部变量,并且仅循环体内可见。
(C)不要在循环过程中修改控制变量的值,否则会导致不可预知的效果。
(5)泛型for
泛型for循环通过一个迭代器(iterator)函数来遍历所有值:
--打印数组a的所有值
for i, v in ipairs(a) do print(v) end
Lua基础库提供了ipairs,这是一个用于遍历数组的迭代器函数。在每次循环中,i会被赋予一个索引值,同时v被赋予一个对应于该索引的数组元素值。
--打印table t的所有key
for k in pairs(t) do print(k) end
泛型for通过不同的迭代器,几乎可以遍历所以东西,而且写出的代码极具可读性。标准库提供了几种迭代器,包括用于迭代文件中每行的io.lines,迭代table元素的pairs、迭代数组元素的ipairs、迭代字符串中单词的string.gmatch等。当然,你也可以编写自己的迭代器。
4、break与return
break与return语句用于跳出当前的块。
break语句用于结束一个循环,它只会跳出包含它的那个内部循环,而不会改变外层的循环。
return语句用于从一个函数中返回结果,或者用于简单地结束一个函数的执行。任何函数的结尾处都有一句隐式的return。