语句

Lua支持多重赋值,就是可以将多个值同时赋值给多个变量。

1
2
3
4
5
6
a, b = 3, 'a'
x ,y = y, x #一行语句进行交换变量
a, b, c = 1, 2
print(a, b, c) --> 1 2 nil
a, b = 1, 2, 3
print(a, b) --> 1 2

控制结构

if / else 语句,lua不支持switch语句,示例如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
if a < 0 then
a = 0
end

if a < 0 then
a = 0
else
a = 1
end

if a < 0 then
a = 0
elseif a = 0 then
a = 1
else
a = 2
end

while循环语句

1
2
3
4
5
local i = 1
while a[i] do
print(a[i])
i = i + 1
end

repeat语句,一条repeat-until语句重复执行循环体直到条件为真时结束。循环体至少会执行一次。跟其他语言的do-while循环有点区别就是,do-while当条件为假的时候停止循环。

1
2
3
4
5
6
a = {1,2,3,4,5}
b = 1
repeat
print(a[b])
b = b + 1
until b > 3

for循环,for循环有两种类型:数字型for循环和泛型for循环。
数字型for循环语法如下:

1
2
3
4
5
6
7
8
9
10
11
for i=exp1, exp2, exp3 do
--循环体
end

# i从exp1变化到exp2,每次变化都以exp3作为步长,并且执行一次循环体。exp3是可选参数,默认值为1

for i=1, 10 do
print(i)
end

# 详细说明下for循环的细节,首先3个表达式exp1,exp2,exp3在循环开始前一次性求值。并且变量i是局部变量,仅在循环体内可见。

泛型for循环,通过一个迭代器函数来遍历所有值。Lua基础库提供了ipairs函数,这个用于遍历数组的迭代器函数。在每次循环中,i会被赋予一个索引值。

1
2
3
4
5
6
7
8
9
10
a = {'a', 'b', 'c'}

for i,v in ipairs(a) do
print(i, v)
end

#输出如下
1 a
2 b
3 c

下面是另外的示例,遍历table中所有的key:

1
2
3
4
5
6
7
8
9
10
11
12
a = {
name = "rcx",
age = 18
}

for k in pairs(a) do
print(k, a[k])
end

#输出如下
name rcx
age 18

Lua标准库提供了几种迭代器,迭代文件中每行的(io.lines)、迭代table元素的(pairs)、迭代数组的(ipairs)、迭代字符串中单词的(string.gmatch)。

for循环特点:

  • 循环变量是循环体的局部变量
  • 不应该给循环变量作任何赋值

break和return语句用于快速跳出当前的块。

函数

调用函数需要将参数放到一对括号中,即使没有参数也需要写一对空括号。对于此规则有特殊的情况,一个函数如果只有一个参数,并且参数是一个字面字符串或者table构造式,那么圆括号便是可有可无。

1
2
3
4
print 'hello world'  <-->  print('hello world')
dofile 'a.lua' <--> dofile('a.lua')
f{x=10,y=20} <--> f({x=10,y=20})
type{} <--> type({})

“形式参数”的使用方式与局部变量很相似,他们是由调用函数时的“实际参数”初始化的。若实参多余形参,则舍弃多余的实参;若实参不足,则多余的形参初始化为nil。

1
2
3
4
5
6
7
8
function f(a, b)
print(a, b)
end

#一下几种调用,实参和形参关系
f(3) a=3,b=nil
f(3,4) a=3,b=4
f(3,4,5) a=3,b=4 (5被丢弃了)

多重返回值,Lua允许函数返回多个结果。编写Lua函数的时候,只需要在return后面列出所有的返回值即可。

1
2
3
4
5
function f()
return 1, 2
end

print(f()) #输出为1 2

Lua会调整一个函数的返回值数量以适应不同的调用情况。

  • 若将函数调用作为一条单独语句时,Lua会丢弃函数的所有返回值。
  • 若函数作为表达式的一部分来调用,Lua只保留函数的第一个返回值。
  • 只有当函数调用的一系列表达式中的最后一个元素(或仅有一个原元素)时,才能获得它的所有返回值。一系列表达式有如下四种:
    - 多重赋值
    - 函数调用时候传入的实参列表
    - table的构造式
    - return语句
    

首先定义些函数:

1
2
3
function foo() end
function foo1() return "a" end
function foo2() return "a", "b" end

在多重赋值中,若函数调用是最后(仅有)的一个表达式,那么Lua会保留其尽可能多的返回值。

1
2
3
4
5
6
7
8
9
10
x, y = foo2()  -- x="a", y="b"
x = foo2() -- x="a", "b"被丢弃
x, y, z = 10, foo2() -- x=10, y="a", x="b"

x, y = foo0() -- x=nil, y=nil
x, y = foo1() -- x="a", y=nil
x, y, z = foo2() -- x="a", y="b", z=nil

x,y = foo2(), 20 -- x="a", y=20 (函数调用不是一系列表达式的最后一个元素)
x, y = foo0(), 20, 30 -- x=nil, y=20, 30被丢弃

当一个函数调用作为另外一个函数最后一个(或仅有)实参时,第一个函数的所有返回值都将作为实参摔入第二个函数。

1
2
3
4
5
6
print(foo0())  -->
print(foo1()) --> a
print(foo2()) --> a b
print(foo2(), 1) --> a 1
print(foo2() .. "x") --> ax
print(foo1(), foo2()) --> a a b

当foo2()出现在一个表达式当中的时候,Lua会将返回值数量调整为1。

table构造式可以完整底接收一个函数调用的所有返回值。

1
2
3
t = {foo0()}  -- t = {}
t = {foo1()} -- t = {"a"}
t = {foo2()} -- t = {"a", "b"}

不过,这种行为只有当一个函数调用作为最后一个元素时候才会发生,其他位置上的函数调用总是只产生一个结果:

1
t = {foo0(), foo2(), 4} -- t[1]=nil,t[2]="a",t[3]=4

最后一种情况是return语句,如return f()这样的语句会返回f的所有返回值。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
function foo(i)
if i == 0 then return foo0()
elseif i == 1 then return foo1()
elseif i == 2 then return foo2()
end
end

print(foo(1)) --> a
print(foo(2)) --> a b
print(foo(0)) -- (无返回值)
print(foo(3)) -- (无返回值)

#也可以将一个函数调用放入一对圆括号中,从而使只返回一个结果
print((foo(0)) --> nil
print((foo(1)) --> a
print((foo(2)) --> a

Lua内置一个unpack函数,它接受一个数组作为参数,并从下标1开始返回该数组的所有元素。

1
2
print(unpack({10,20,30})) --> 10  20  30
a, b = unpack({10,20,30}) -- a=10,b=20, 30被丢弃

—EOF—