Lua 迭代器和閉包

2021-10-02 19:43:51 字數 2742 閱讀 3477

內容來自《lua程式設計(第四版)》18.1節 —— 迭代器和閉包。

迭代器(iterator)是一種可以讓我們遍歷乙個集合中所有元素的**結構。在 lua 語言中,通常使用函式表示迭代器:每一次呼叫函式時,函式會返回集合中的「下乙個」元素。乙個典型的例子就是io.read,每次呼叫該函式時它都會返回標準輸入中的下一行,子啊沒有可以讀取的行時返回 nil。

所有迭代器都需要在連續的呼叫之間儲存一些狀態,這樣才能知道當前迭代所處的位置及如何從當前位置進到下乙個位置。對於函式io.read而言,c 語言會將狀態儲存在流的結構體中。對於我們自己的迭代器而言,閉包則為儲存狀態提供了一種良好的機制。乙個閉包就是乙個可以訪問其自身環境中乙個或多個區域性變數的函式。這些變數將連續呼叫過程中的值,並將其儲存在閉包中,從而使得閉包能夠記住迭代所處位置。

要建立乙個新的閉包,必須建立非區域性變數。因此,乙個閉包結構通常涉及兩個函式:閉包本身和乙個用於建立該閉包及其封裝變數的工廠(factory)

作為示例,先為列表編寫乙個簡單迭代器,與ipairs不同,帶迭代器並不是返回每個元素的索引而是返回元素的值:

function values

(t) local i =

0return

function

() i = i +1;

return t[i] end

end

這個例子中,values就是工廠。每當呼叫這個工廠時,它就會建立乙個新的閉包(即迭代器本身)。這個閉包將它的狀態儲存在其外部的變數 t 和 i 中,這兩個變數也是由values建立的。每次呼叫這個迭代器時,就從列表 t 中返回乙個值,在遍歷完最後乙個元素後,迭代器返回 nil,迭代結束。

這樣的迭代器可以在while迴圈中使用:

t =

iter =

values

(t)-- 建立迭代器

while

true

do local element =

iter()

-- 呼叫迭代器

if element == nil then break end

print

(element)

end

不過,使用泛型for更簡單,畢竟泛型for就是為這種迭代器而設計的:

t =

for element in

values

(t)do

print

(element)

end

泛型for為一次迭代迴圈做了所有的記錄工作:它在內部儲存了迭代韓素華,因此不需要變數iter;它在每次做新的迭代時都會再次呼叫迭代器,並在迭代器返回 nil 時結束。下面是乙個更高階的例子,它可以遍歷來自標準輸入的所有單詞:

function allwords()

local line = io.

read()

-- 當前行

local pos =

1-- 在當前行的位置

return

function()

-- 迭代函式

while line do

-- 當還有行時迴圈

local w, e = string.

match

(line,

"(%w+)()"

, pos)

if w then -- 發現乙個單詞

pos = e -- 下乙個位置位於該單詞後

return w -- 返回該單詞

else

line = io.

read()

-- 沒找到單詞;嘗試下一行

pos =

1-- 從第乙個位置重新開始

endend

return nil -- 沒有行了,迭代結束

endend

為了完成這樣的遍歷,我們需要儲存兩個值:當前行的內容(變數line)及當前行的當前位置(變數pos)。有了這些資料,我們就可以不斷產生下乙個單詞。這個迭代函式的主要部分時呼叫函式string.match,以當前位置作為起始在當前行中搜尋乙個單詞。函式使用模式%w+來匹配乙個單詞(也就是匹配乙個或多個字母或數字字元),如果找到了乙個單詞,就捕獲並返回這個單詞及該單詞之後的第乙個字元的位置(乙個空匹配),迭代函式則更i效能當前位置並返回該單詞;否則,迭代器讀取新的一行,然後重複上述搜尋過程。在所有的行都被讀取完後,迭代函式返回 nil 以表示迭代結束。

儘管迭代器本身比較複雜,但allwords的使用還是很簡單易懂的:

for word in allwords()

doprint

(word)

end

對於迭代器而言,一種很常見的情況就是:編寫迭代器可能不太容易,但是使用迭代器卻十分簡單,這也不是大問題,因為使用 lua 語言程式設計的終端使用者一般不會去定義迭代器,而是使用那些宿主因應用已經提供的迭代器。

Lua筆記11 迭代器和閉包

迭代器是一種支援指標型別的結構,它可以遍歷集合的每乙個元素。在lua中我們常常使用函式來描述迭代器,每次呼叫該函式就返回集合的下乙個元素。迭代器需要保留上一次成功呼叫的狀態和下一次成功呼叫的狀態,也就是他知道來自於 和將要前往 閉包提供的機制可以很容易實現這個任務。記住 閉包是乙個內部函式,它可以訪...

Lua初識之迭代器與閉包

一 迭代器與閉包 迭代器是一種支援指標型別的結構,它可以遍歷集合的每乙個元素 在lua中我們常常使用函式來描述迭代器,每次呼叫該函式就返回集 合的下乙個元素 寫乙個方法實現迭代 function list iter t local i 0 定義區域性變數 i local n table.getn t...

Lua for 迭代器和閉包

for迴圈分為兩種 數值型 numerical for和泛型 generic for。1 數值型for 語法如下 for var exp1,exp2,exp3 do something end上述迴圈中,var的作用範圍為for迴圈內部,其值從exp1變化到exp2之前,每次迴圈都會執行someth...