第一版是針對 Lua 5.0 編寫。雖然在後續版本中仍然有很大的相關性,但還是有一些差異。
第四版針對 Lua 5.3,可以在 Amazon 和其他書店買到。
購買這本書,您也可以幫助支援 Lua 專案


7.2 – 通用 for 的語意

這些先前反覆運算器的一個缺點是,我們需要為每個新迴圈建立一個新的封閉。在大部分情況下,這不是一個真正問題。例如,在 allwords 反覆運算器中,與讀取整個檔案的成本相比,建立一個封閉的成本可以忽略不計。但是,在少數情況下,這種開銷可能是不可取的。在這種情況下,我們可以使用通用 for 本身來保留反覆運算狀態。

我們看到通用 for 在迴圈期間會在內部保留反覆運算器函式。實際上,它保留三個值:反覆運算器函式、不變狀態控制變數。現在讓我們看看詳細資訊。

通用 for 的語法如下

    for <var-list> in <exp-list> do
      <body>
    end
其中 <var-list> 是由逗號分隔的一個或多個變數名稱清單,而 <exp-list> 是由逗號分隔的一個或多個表達式清單。通常,表達式清單只有一個元素,即對反覆運算器工廠的呼叫。例如,在程式碼中
    for k, v in pairs(t) do
      print(k, v)
    end
變數清單是 k, v;表達式清單有一個元素 pairs(t)。通常,變數清單也只有一個變數,如下所示
    for line in io.lines() do
      io.write(line, '\n')
    end
我們將清單中的第一個變數稱為控制變數。在迴圈期間,它的值永遠不會是 nil,因為當它變為 nil 時,迴圈就會結束。

for 執行的第一件事是評估 in 之後的表達式。這些表達式應產生 for 保留的三個值:反覆運算器函式、不變狀態和控制變數的初始值。就像在多重賦值中,清單的最後一個(或唯一一個)元素才能產生多個值;並且值的數量會調整為三個,額外的值會被捨棄或視需要新增 nil。(當我們使用簡單的反覆運算器時,工廠只會傳回反覆運算器函式,因此不變狀態和控制變數會取得 nil。)

在這個初始化步驟之後,for 會使用兩個參數呼叫迭代器函數:不變狀態和控制變數。(請注意,對於 for 結構,不變狀態完全沒有意義。它只會從初始化步驟取得這個值,並在呼叫迭代器函數時傳遞它。)然後,for 會將迭代器函數傳回的值指定給其變數清單所宣告的變數。如果傳回的第一個值(指定給控制變數的值)為 nil,則迴圈會終止。否則,for 會執行其主體並再次呼叫迭代函數,重複此程序。

更精確地說,像這樣的結構

    for var_1, ..., var_n in explist do block end
等於下列程式碼
    do
      local _f, _s, _var = explist
      while true do
        local var_1, ... , var_n = _f(_s, _var)
        _var = var_1
        if _var == nil then break end
        block
      end
    end
因此,如果我們的迭代器函數為 f,不變狀態為 s,而控制變數的初始值為 a0,則控制變數會迴圈遍歷值 a1 = f(s, a0)a2 = f(s, a1),等等,直到 ainil。如果 for 有其他變數,它們只會取得 f 的每次呼叫傳回的額外值。