控制结构教程

lua-users home
wiki

控制结构让你的程序可以做出选择,或者多次运行相同的代码段。

if 语句

if 语句允许你根据条件运行不同的代码。

if condition then
  block
elseif condition2 then
  block
elseif condition3 then
  block
else
  block
end

ifelseif 部分按顺序检查,一旦其中一个条件为真,它就会运行其下的代码块并跳到末尾,忽略其后的任何其他 elseif 条件。如果没有任何条件匹配,则运行 else 代码块。最后,elseifelse 部分是可选的。

> n = 5
> if n > 5 then print("greater than 5") else print("less than 5") end
less than 5
> n = 7
> if n > 5 then print("greater than 5") else print("less than 5") end
greater than 5

一个更复杂的例子

> n = 12
> if n > 15 then
>> print("the number is > 15")
>> elseif n > 10 then
>> print("the number is > 10")
>> elseif n > 5 then
>> print("the number is > 5")
>> else
>> print("the number is <= 5")
>> end
the number is > 10

注意,即使多个条件为真,也只打印了一条消息:这是因为一旦一个条件匹配,if 语句就会跳过检查其他条件。

while 循环

while condition do
  block
end

这会在循环中反复运行代码块,但在每次迭代中,它首先检查条件,如果条件为假,则跳到 end,退出循环。如果条件始终为假,则代码块永远不会运行。

> i = 1
> while i <= 10 do
>> print(i)
>> i = i + 1
>> end
1
2
3
4
5
6
7
8
9
10

repeat 循环

repeat
  block
until condition

while 循环相同,只是条件被反转(在为真时退出循环),并且在第一次迭代后检查,因此代码保证至少运行一次。

> i = 5
> repeat
>> print(i)
>> i = i - 1
>> until i == 0
5
4
3
2
1

数字 for 循环

for variable = start, stop, step do
  block
end

运行代码块,variable 首先等于 start,然后不断增加 step 量并再次运行代码块,直到它大于 stopstep 可以省略,默认值为 1。

你也可以使 step 为负数,循环将在计数器变量小于停止值时停止。

> for i = 1, 5 do
>> print(i)
>> end
1
2
3
4
5
> for i = 1, 100, 8 do
>> print(i)
>> end
1
9
17
25
33
41
49
57
65
73
81
89
97
> for i = 3, -3, -1 do
>> print(i)
>> end
3
2
1
0
-1
-2
-3
> for i = 0, 1, 0.25 do
>> print(i)
>> end
0
0.25
0.5
0.75
1
> for i = 1, 3 do
>> for j = 1, i do
>> print(j)
>> end
>> end
1
1
2
1
2
3

还要记住,for 循环中的变量只在代码块内可见,循环退出后,它将不再包含最后一个值。

迭代器 for 循环

for var1, var2, var3 in iterator do
  block
end

for 循环的迭代器版本接受一个特殊的迭代器函数,并且可以有任意数量的变量。循环执行的操作、它需要的变量数量以及这些变量将被设置为的值取决于迭代器。

这主要适用于表,表还没有介绍,但这里有一个例子让你了解一下

> tbl = {"a", "b", "c"}
> for key, value in ipairs(tbl) do
>> print(key, value)
>> end
1       a
2       b
3       c

这里,ipairs 是迭代器,它按顺序获取表中的编号条目。

break 语句

break 语句会导致 Lua 跳出当前循环。

> i = 3
> while true do -- infinite loop
>> print(i)
>> i = i + 1
>> if i > 6 then
>> break
>> end
>> end
3
4
5
6

对于嵌套循环,break 只影响最内层的循环。

> for i = 1, 2 do
>> while true do
>> break
>> end
>> print(i)
>> end
1
2

在循环之外使用 break 会导致语法错误。

> break
stdin:1: <break> at line 1 not inside a loop

continue 语句的替代方案

许多其他语言都有一个 continue 语句,它会跳过当前循环的最内层迭代的剩余部分。在 Lua 5.2 中,可以使用 goto 来模仿这种行为。

> for i = 1, 10 do
>> if i>3 and i<6 then goto continue end
>> print(i)
>> ::continue:: -- a name surrounded in :: :: is a goto label
>> end
1
2
3
6
7
8
9
10

Lua 5.1 及更早版本没有 goto,但有其他解决方法。

> for i = 1, 10 do
>> if not (i>3 and i<6) then
>> print(i)
>> end
>> end
1
2
3
6
7
8
9
10
> for i = 1, 10 do repeat
>> if i>3 and i<6 then break end
>> print(i)
>> until true end
1
2
3
6
7
8
9
10

条件

条件不一定要是布尔值。实际上,任何值都是有效的条件:nilfalse 使条件为假,其他任何值(包括 0)都使条件为真。

> if 5 then print("true") else print("false") end
true
> if 0 then print("true") else print("false") end
true
> if true then print("true") else print("false") end
true
> if {} then print("true") else print("false") end
true
> if "string" then print("true") else print("false") end
true
> if nil then print("true") else print("false") end
false
> if false then print("true") else print("false") end
false

还有一些语言,变量赋值被认为是表达式(因此它可以用作子表达式),所以像这样的代码被写成

> i = 0
> while (i = i + 1) <= 10 do print(i) end
stdin:1: ')' expected near '='
但在 Lua 中,赋值是一个语句,上面的例子是一个语法错误。

if/else 作为表达式

一些语言有一个三元运算符,它像 if/else 语句一样工作,但可以用作子表达式。如果条件为真,它会计算一个表达式,否则它会计算另一个表达式。

Lua 没有这样的运算符,但在许多情况下,可以使用 andor 逻辑运算符来模仿它。这是因为两个原因:这些运算符如果仅从左侧结果就知道逻辑结果,就不会执行右侧表达式,而且它们直接返回其子表达式的结果,而不是将其转换为布尔值。

> = true and print("test")
test
nil
> = false and print("test") -- 'and' is always false if one of the sides are false, don't bother running the other expression
false
> = true or print("test") -- 'or' is always true if one of the sides are true, don't bother running the other expression
true
> = false or print("test")
test
nil
> = 8 or 5
8
> = true and "text"
text

这可以用来创建一个简单的 if/else 表达式。

> condition = true
> = condition and 2 or 4
2
> condition = false
> = condition and 2 or 4
4
> = condition and print("a") or print("b") -- only the "false" branch is run, otherwise both a and b would be printed
b
nil

请记住,“and” 的优先级高于 “or”:如果条件为假,它会使 “and” 表达式放弃并返回 false。这将使 “or” 部分尝试其右侧表达式并返回其值。如果条件为真,“and” 将返回其右侧表达式。然后将其传递给 “or”,它会看到左侧结果是一个真条件,并直接返回它。

请注意,我们假设真分支的结果是一个充当真条件的值。这导致了一个问题:真分支不能计算为 nilfalse,因为那样的话假分支也会被执行,并且它的值会被返回。

> condition = true
> = condition and false or true -- wrong result!
true

这是因为整个“and”子表达式现在为假,导致“or”尝试运行其另一个子表达式。但是从假分支返回假值是可以的。事实上,如果你遇到像上面例子这样的情况,你可以简单地反转条件并交换分支的内容。

> condition = true
> = not condition and true or false
false

如果两个分支都必须返回一个充当假条件的值,那么有一种方法可以使用“or true”运算符。

> condition = 1
> =condition >= 1 and (print("condition >= 1") or true) or print("condition < 1")
condition >= 1
true

最近更改 · 偏好设置
编辑 · 历史记录
最后编辑于 2023 年 6 月 5 日下午 12:03 GMT (差异)