2.4 lua 控制结构

流程控制语句对于程序设计来说特别重要,它可以用于设定程序的逻辑结构。一般需要与条件判断语句结合使用。Lua 语言提供的控制结构有 if,while,repeat,for,并提供 break 关
键字来满足更丰富的需求。

if/else

if-else 是我们熟知的一种控制结构。Lua 跟其他语言一样,提供了 if-else 的控制结构。语法上更接近shell的语言,逻辑结构上和其他语言没有较大的区别,直接上实例,一看便知。

单分支if-end

1  
2  
3  
4  
5  
x = 10  
if x > 0 then  
    print("x is a positive number")  
end  

—|—

双分支if-else-end

1  
2  
3  
4  
5  
6  
7  
x = 10  
if x > 0 then  
    print("x is a positive number")  
else  
    print("x is a non-positive number")  
end  

—|—

多分支if-elseif-else-end

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
score = 90  
if score == 100 then  
    print("Very good!Your score is 100")  
elseif score >= 60 then  
    print("Congratulations, you have passed it,your score greater or equal to 60")  
--此处可以添加多个elseif  
else  
    print("Sorry, you do not pass the exam! ")  
end  
--运行输出:Congratulations, you have passed it,your score greater or equal to 60  

—|—

特别注意| 与 C 语言的不同之处是 else 与 if 是连在一起的,若将 else 与 if 写成 “else if” 则相当于在else 里嵌套另一个 if 语句,如下代码:

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
score = 0  
if score == 100 then  
    print("Very good!Your score is 100")  
elseif score >= 60 then  
    print("Congratulations, you have passed it,your score greater or equal to 60")  
else  
    if score > 0 then  
        print("Your score is better than 0")  
    else  
        print("My God, your score turned out to be 0")  
    end --与上一示例代码不同的是,此处要添加一个end  
end  

—|—

从上述实例中可以发现,除了else if这种形式较elseif多了一个end外看起来并没有什么区别。上述实例中else if在判断的最后,如果在中间的话,意味着后面的elseif将会出现语法错误。

while

Lua 跟其他常见语言一样,提供了 while 控制结构,语法上也没有什么特别的。但是没有提供do-while 型的控制结构,但是提供了功能相当的 repeat
while 型控制结构语法如下,当表达式值为假( 即 falsenil) 时结束循环。也可以使用break 语言提前跳出循环。

1  
2  
3  
while 表达式 do  
    --body  
end  

—|—

1  
2  
3  
4  
5  
6  
7  
8  
--示例代码,求 1 + 2 + 3 + 4 + 5 的结果  
x = 1  
sum = 0  
while x <= 5 do  
    sum = sum + x  
    x = x + 1  
end  
print(sum) -->output 15  

—|—

特别注意:
Lua 并没有像许多其他语言那样提供类似 continue 这样的控制语句用来立即进入下一个循环迭代( 如果有的话) 。因此,我们需要仔细地安排循环体里的分支,以避免这样的需求。

没有提供 continue ,却也提供了另外一个标准控制语句 break ,可以跳出当前循环。例如遍历 table,查找值为 11 的数组下标索引:

1  
2  
3  
4  
5  
6  
7  
8  
local t = {1, 3, 5, 8, 11, 18, 21}  
local i  
for i, v in ipairs(t) do  
    if 11 == v then  
        print("index[" .. i .. "] have right value[11]")  
        break  
    end  
end  

—|—

repeat

Lua 中的 repeat 控制结构类似于其他语言( 如:C++ 语言) 中的 do-while,但是控制方式是刚好相反的。简单点说,执行 repeat 循环体后,直到 until 的条件为 时才结束,而其他语言( 如:C++ 语言) 的 do-while 则是当条件为假时就结束循环。

1  
2  
3  
4  
5  
x = 10  
repeat  
    print(x)  
until false  
--该代码将导致死循环,因为until的条件一直为假,循环不会结束  

—|—

除了条件相反外,repeatwhile是一样的。

for

for 语句有两种形式:数字 for( numeric for) 和范型 for( generic for)。

数字for

1  
2  
3  
for var = begin, finish, step do  
    --body  
end  

—|—

关于数字 for 需要关注以下几点:

  1. var 从 begin 变化到 finish,每次变化都以 step 作为步长递增 var;
  2. begin、finish、step 三个表达式只会在循环开始时执行一次;
  3. 第三个表达式 step是可选的,默认为 1;
  4. 控制变量 var 的作用域仅在 for 循环内,需要在外面控制,则需将值赋给一个新的变量;
  5. 循环过程中不要改变控制变量的值,那样会带来不可预知的影响.
1  
2  
3  
for i = 10, 1, -1 do  
    print(i)  
end  

—|—

如果不想给循环设置上限的话,可以使用常量 math.huge:

1  
2  
3  
4  
5  
6  
for i = 1, math.huge do  
    if (0.3*i^3 - 20*i^2 - 500 >=0) then  
        print(i)  
        break  
    end  
end  

—|—

泛型for

泛型 for 循环通过一个迭代器( iterator) 函数来遍历所有值:

1  
2  
3  
4  
5  
-- 打印数组a的所有值  
local a = {"a", "b", "c", "d"}  
for i, v in ipairs(a) do  
print("index:", i, " value:", v)  
end  

—|—

结果:

1  
2  
3  
4  
index: 1 value: a  
index: 2 value: b  
index: 3 value: c  
index: 4 value: d  

—|—

注意到在上述实例中使用到ipairs函数。Lua 的基础库提供了ipairs,这是一个用于遍历 数组 的迭代器函数。在每次循环中,i 会被赋予一个索引值,同时 v 被赋予一个对应于该索引的数组元素值。那么如何遍历table呢?lua提供了pairs函数可以遍历tbale中的key.

1  
2  
3  
4  
-- 打印table t中所有的key  
for k in pairs(t) do  
    print(k)  
end  

—|—

从外观上看泛型 for 比较简单,但其实它是非常强大的。通过不同的迭代器,几乎可以遍历所有的东西, 而且写出的代码极具可读性。标准库提供了几种迭代器,包括用于迭代文件中每行的( io.lines) 、 迭代 table 元素的( pairs) 、迭代数组元素的( ipairs) 、迭代字符串中单词的( string.gmatch) 等。
泛型 for 循环与数字型 for 循环有两个相同点:

  1. 循环变量是循环体的局部变量;
  2. 决不应该对循环变量作任何赋值。

特别注意: 在 LuaJIT 2.1 中, ipairs() 内建函数是可以被 JIT 编译的,而 pairs() 则只能被解释执行。因此在性能敏感的场景,应当合理安排数据结构,避免对哈希表进行遍历。事实上,即使未来 pairs 可以被 JIT 编译,哈希表的遍历本身也不会有数组遍历那么高效,毕竟哈希表就不是为遍历而设计的数据结构。

糖果

糖果
LUA教程

Lapis框架的常用处理方法

Lapis框架的常用处理方法 Continue reading

MoonScript实现选择排序

Published on February 26, 2017

MoonScript与Redis客户端

Published on January 19, 2017