教學指南 |
|
for
語句有兩種不同的形式。一可用於遍歷數值進程,另一可用於遍歷稱為「迭代器」的函數。參考手冊的 2.4.5 部分中涵蓋了 for
語句。[1]
數值進程版本的 for
採用以下語法
for
variable =
from_exp ,
to_exp [,
step_exp] do
block end
此語句會在進入 for
區塊前將 variable 的值設定為 from_exp。僅在 variable 未超過最後一個值 to_exp 時才會進入區塊。這包含第一遍遍歷迴圈時。區塊每次結束時,會將 step_exp 加到 variable 中。指定步驟表示式為選用。如果未指定,則使用 1。例如:
> for i = 1,3 do print(i) end -- count from 1 to 3 1 2 3 > for i = 3,1 do print(i) end -- count from 3 to 1 in steps of 1. zero iterations! > for i = 3,1,-1 do print(i) end -- count down from 3 to 1 3 2 1 > for i=1,0,-0.25 do print(i) end -- we're not limited to integers 1 0.75 0.5 0.25 0
i
會是 for
迴圈作用範圍內的區域變數,也就是說:> print(i) -- after the above code nil
for v = e1, e2, e3 do block end
等於以下 Lua 程式碼
do local var, limit, step = tonumber(e1), tonumber(e2), tonumber(e3) if not (var and limit and step) then error() end while (step > 0 and var <= limit) or (step <= 0 and var >= limit) do local v = var block var = var + step end end
for
迴圈的第二種形式採用語法:
for
var {, var} in
explist do
block end
explist 在進入迴圈前先評估一次。其結果是一個 iterator function(用於設定 var 值)、一個 state(可從其中讀取值)及一個 initial value(用於繼續遍歷)。
Lua 提供一個 pairs()
函數,為我們建立 explist 資訊以便遍歷表格。pairs()
函數允許遍歷 key-value 對。請注意,返回項目順序未定義,即使是索引表格也不例外。
> for key,value in pairs(t) do print(key,value) end 3 10 1 3 4 17 2 7 pi 3.14159 banana yellow
ipairs()
函數允許遍歷 index-value 對。這些是「key-value」對,其中鍵是陣列中的索引。保證以索引的數值順序返回元素順序,而非整數鍵會直接跳過。使用與上例中相同的表格:
> for index,value in ipairs(t) do print(index,value) end 1 3 2 7 3 10 4 17
next(table [,index])
函數協助遍歷表格。當提供表格和索引時,它會從表格中返回下一組 key-value 對,例如:
> = next(t) -- index will be nil, the beginning 1 3 > = next(t,4) pi 3.14159
與 pairs()
一樣,返回項目的順序並未定義;索引鍵可以任何順序返回,而不僅是數值遞增。pairs()
函數會傳回包含有 next()
的 explist,因此我們可以遍歷表格。我們可以將自己的表示式清單傳遞給 for
語句,如下所示:
> for key,value in next,t,nil do print(key,value) end 1 3 2 7 3 10 4 17 pi 3.14159 banana yellow
next,table,nil
作為表達式清單到 for
陳述式。我們在這裡表示我們要使用迭代器函式 `next()`,在表 t
,從 nil
(開頭) 開始。for
陳述式會持續執行直到 next()
函式傳回 nil
(表的結尾)。
Lua 提供其他實用迭代器,像在 io
函式庫中的 io.lines([filename])
。我們可以透過建立一個自訂檔包含幾行文字來示範這個。
> io.output(io.open("my.txt","w")) > io.write("This is\nsome sample text\nfor Lua.") > io.close()
io.lines
迭代器來讀取它> for line in io.lines("my.txt") do print(line) end This is some sample text for Lua.
io
函式庫提供另一種方法來反覆處理文字檔的行。
> file = assert(io.open("my.txt", "r")) > for line in file:lines() do print(line) end This is some sample text for Lua. > file:close()
與 io.lines()
有哪些差異?
您必須明確開啟並關閉檔案。此優點之一是,如果無法開啟檔案,您可以好好處理此失敗。在此,assert
與 io.lines
有相同效果:直譯器會停止並顯示指向有問題行的錯誤訊息;但您可以測試 file
的 nil
值並執行其他動作。
另一個優點是,您可以從任何行開始迴圈
file = assert(io.open("list.txt", "r")) local line = file:read() if string.sub(line, 1, 1) ~= '#' then ProcessLine(line) -- File doesn't start with a comment, process the first line end -- We could also loop on the first lines, while they are comment -- Process the remainder of the file for line in file:lines() do ProcessLine(line) end file:close()
我們可以撰寫自己的迭代器,類似於 next()
,以反覆處理任何資料序列。這在 IteratorsTutorial 中有更詳細的說明。