控制結構
Lua語言提供了一組精簡且常用的控制結構,包括用於條件執行的if以及用戶循環的while、repeat和for。所有的控制結構語法上都有一個顯示的終結符:end用於終結if、for及while結構,until用於終結repeat結構。
控制結構的條件表達式的結果可以是任何值。Lua語言將所有不是false和nil的值當做真。
if then else
if 語句先測試其條件,並根據條件是否滿足執行相應的then部分或else部分。else部分是可選的。
if a<0 then a == end
if a <b then return a else return b end
if line > MAXLINES then
showpage()
line = 0
end
如果要編寫嵌套的if語句,可以使用elseif。它類似於在else後面緊跟一個if,但可以避免重複使用end:
if op == "+" then
r = a + b
elseif op == "-" then
r = a - b
elseif op == "*" then
r = a * b
elseif op == "/" then
r = a / b
else
error("invalid operation")
end
由於Lua語言不支持switch語句,所以這種一連串的else-if語句比較常見。
while
當條件爲真時while循環會重複執行其循環體。Lua語言先測試while語句的條件,若條件爲假則循環結束;否則,Lua會執行循環體並不斷地重複這個過程。
local i = 1
while a[i] do
print(a[i])
i = i + 1
end
repeat
repeat-until語句會重複執行其循環體知道條件爲真時結束。由於條件測試在循環體之後執行,所以循環體至少會執行一次。
-- 輸出第一個非空的行
local line
repeat
line = io.read()
until line ~= " "
print(line)
和大多數其他編程語言不同,在Lua語言中,循環體內聲明的局部變量的作用於包括測試條件:
-- 使用Newton-Raphson法計算"x"的平方根
local sqr = x / 2
repeat
sqr = (sqr + x / sqr) /2
local error = math.abs(sqr^2 - x)
until error < x/ 10000 -- 局部變量'error'此時仍然可見
數值型for
for 語句有兩種形式:數值型for和泛型for。
數值型for的語法如下:
for var = exp1 , exp2, exp3 do
something
end
在這種循環中,var的值從exp1變化到exp2之前的每次循環會執行something。並且在每次循環結束後將步長exp3增加到var上。第三個表達式exp3是可選的,若不存在,Lua語言會默認步長值爲1.如果不想給循環設置上限,可以使用常量math.huge:
for i = 1, math.huge do
if (0.3*i^3 - 20*i^2 - 500 >= 0 ) then
pirnt(i)
break
end
end
爲了更好地使用for循環,還需要了解一些細節。首先,在循環開始前,三個表達式都會運行一次;其次,控制變量是被for語句自動聲明的局部變量,且其作用範圍僅限於循環體內。一種典型的錯誤是認爲控制變量在循環結束後仍然存在:
for i = 1 , 10 do print(i) end
max = i -- 可能會出錯
如果需要在循環結束後使用控制變量的值,則必須將控制變量的值保存到另一個變量中:
-- 在一個列表中尋找一個值
local found = nil
for i = 1 , #a do
if a[i] < 0 then
found = i
break
end
end
print(found)
最後,不要改變控制變量的值,隨意改變控制變量的值可能產生不可預知的結果。如果要在循環正常結束前停止for,那麼可以使用break語句。
泛型for
泛型for遍歷迭代函數返回的所有值。例如我們已經在很多示例中看到過的pairs、ipairs和io.lines等。雖然泛型for看似簡單,但它的功能非常強大。使用恰當的迭代器可以在保證代碼可讀性的情況下遍歷幾乎所有的數據結構。
當然,我們也可以自己編寫迭代器。儘管泛型for的使用很簡單,但編寫迭代函數卻有不少細節需要注意。
與數值型for不同,泛型for可以使用多個變量,這些變量在每次循環時都會更新。當第一個變量變爲nil時,循環終止。像數值型for一樣,控制變量時循環體中的局部變量,我們也不應該在循環中改變其值。