第一版是為 Lua 5.0 編寫的。儘管在很大程度上仍然適用於後續版本,但仍有一些不同之處。
第四版針對 Lua 5.3,可在 Amazon 和其他書店購買。
購買本書,您還可以幫助支援 Lua 專案


7.5 – 真正的迭代器

「迭代器」這個名稱有點令人誤解,因為我們的迭代器並不會進行迭代:進行迭代的是 for 迴圈。迭代器只提供迭代的連續值。或許更好的名稱應該是「產生器」,但「迭代器」已經在其他語言中廣泛使用,例如 Java。

然而,還有另一種建立迭代器的方法,其中迭代器實際上會進行迭代。當我們使用此類迭代器時,我們不會撰寫迴圈;相反地,我們只需呼叫迭代器,並提供一個引數來描述迭代器在每次迭代時必須執行的動作。更具體地說,迭代器接收一個函式作為引數,並在迴圈內呼叫該函式。

舉一個具體的例子,讓我們再次使用這種樣式改寫 allwords 迭代器

    function allwords (f)
      -- repeat for each line in the file
      for l in io.lines() do
        -- repeat for each word in the line
        for w in string.gfind(l, "%w+") do
          -- call the function
          f(w)
        end
      end
    end
要使用此類迭代器,我們必須提供迴圈主體作為函式。如果我們只想列印每個字詞,我們只需使用 print
    allwords(print)
更常見的是,我們使用匿名函式作為主體。例如,下一個程式碼片段計算輸入檔案中「hello」這個字詞出現的次數
    local count = 0
    allwords(function (w)
      if w == "hello" then count = count + 1 end
    end)
    print(count)
使用先前的迭代器樣式撰寫的相同任務並無太大不同
    local count = 0
    for w in allwords() do
      if w == "hello" then count = count + 1 end
    end
    print(count)

真正的迭代器在舊版本的 Lua 中很流行,當時該語言沒有 for 陳述式。它們與產生器樣式迭代器相比如何?兩種樣式的大約負擔相同:每次迭代一個函式呼叫。一方面,使用第二種樣式撰寫迭代器比較容易(儘管我們可以使用協同程式來恢復這種容易性)。另一方面,產生器樣式更靈活。首先,它允許兩個或更多並行迭代。(例如,考慮逐字比較兩個檔案的迭代問題。)其次,它允許在迭代器主體內使用 breakreturn。(使用真正的迭代器,return 會從匿名函式返回,而不是從執行迭代的函式返回。)