第04章 语句
赋值(assignment)
Lua 有个不同于 C, Java, JavaScript 等的赋值特点:它可以多重赋值——一次将多个值赋给多个变量。
a, b = "hello, world!", 2012
print(a, b) --> hello, world! 2012
多重赋值都是先对右边的元素求值,然后赋给左边的变量,如此,lua 中的值交换写起来比其他语言方便的多,一句话搞定:
a, b = b, a -- 交换 a 和 b
c[i], c[j] = c[j], c[i] -- 交换 c[i] 和 c[j]
局部变量和块(block)
局部变量以 local 声明,作用域仅限于它所在的块(block),或一个 chunck 。一个 block 是一个控制结构的执行体,或者是一个函数的执行体,或者是一个程序块(chunk)。一个函数的形参是这个函数体的局部变量。
如果局部变量和全局变量同名,可以如此处理:
local foo = foo -- 声明一个局部变量 foo, 并用全局变量 foo 来初始化它。
编程原则:“尽可能使用局部变量”。
控制结构
if/else
a = -33
if a > 0 then
print(1)
elseif a == 0 then
print(0)
else
print("other")
end
if/else 结构如上例所示,其中 elseif 可有0个或多个,如果分支选择,最后一个分支必须用 else.
Lua 不支持 switch 结构,因此代码中可能出现大量的 if/else 语句。
while
local a = {"Sunday", "Monday", "Tuesday", "Wednesday","Thursday", "Friday", "Saturday"}
local i = 1
while a[i] do
print(a[i])
i = i + 1 -- lua 中貌似没有 ++ 和 -- 运算, 只能这么用
end
以上代码输出:
Sunday
Monday
Tuesday
Wednesday
Thursday
Friday
Saturday
依次打印了数组的内容。
repeat
b = {-3, -2, -1, 0}
local i = 1
while b[i] > 0 do
print(b[i])
i = i + 1
end
i = 1
repeat
local v = b[i]
print(v)
until b[i] <0
上面的代码输出:
-3
是 repeat 循环的输出。repeat 有点像 do ... while 结构,至少执行一次。这里,循环体中的局部变量的作用域会延伸到条件测试部分。
numberic for
Lua 中第一种 for 是所谓的 numberic for:
for var=start_value, end_value, step_value do
<循环体>
end
for 关键字后以此是:起始值(start value),终止值(end value),步进量(step value)。其中 setp value 可选,如果不填写,系统缺省为1. for 的三个变量 start_value, end_value, step_value 是一次性求值的,并会被作为循环体内的局部变量。示例代码如下:
for p = 1, 100, 21 do
print(p)
end
以上代码输出:
1
22
43
64
85
另一个例子:
a = {1, 2, 3; -3, -9}
local found = nil
for i=1, #a do
if a[i] < 0 then
found = i
break
end
end
print(found) --> 4
print(a[found]) --> -3
generic for
泛型 for (generic for), lua 中的第二种 for,它通过 iterator(迭代器) 函数来遍历所有的值。其实这东西,在 Java 中也有体现,如通过 for/each 遍历泛型数组或集合类等。
a = {1, 2, 3; -3, -9}
for i, v in ipairs(a) do
print(v)
end
它的输出是:
1: 1
2: 2
3: 3
4: -3
5: -9
ipairs 函数由 lua 的基础库提供,用以遍历数组的迭代器函数。在每次循环中,i 被赋予当前遍历到的元素的索引值,v 就是被遍历到原书的值。这里 i 从1开始,所以要是把 a 中的元素改为从0开始的话,头一个元素就不显示的。
a = {[0]=1, 2, 3; -3, -9}
for i, v in ipairs(a) do
print(tostring(i) .. ": " .. v)
end
的输出是:
1: 2
2: 3
3: -3
4: -9
上面的输出中,index 为0的元素没了。这里也可以看出把 index 设置为0带来的问题。
系统提供了几种迭代器:
- io.lines 迭代文件中每行
- pairs 迭代 table 元素
- ipairs 迭代数组元素
- string.gmatch 迭代字符串中单词
还可以自定义迭代器 TODO 这部分可以在将来单独整理(ch7 会单独讲到这个问题)
break/return
Lua 限定只能用于 block 或 chunk 的最后,如果中间要使用,可以显示用 do ... end 调用