控制结构教程

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。

你也可以使用负数步长,当计数器变量小于 stop 值时,循环会停止。

> 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

RecentChanges · preferences
编辑 · 历史
最后编辑于 2023 年 6 月 5 日 上午 6:03 GMT (差异)