lua學習之迭代器與泛型 for 第三篇

迭代器與泛型 for 3

具備複雜狀態的迭代器

  1. 使用 closure 能夠保存迭代器所需保存的全部狀態
  2. 也能夠將迭代器所需的全部狀態打包爲一個 table 並保存在 恆定狀態中
  3. 在循環過程當中 恆定狀態 老是同一個 table
  4. 但這個 table 的內容卻能夠改變即在循環過程當中改變 table 數據
  5. 因爲這種迭代器能夠保存全部數據將其存儲到 恆定狀態中,所以第二個參數 控制變量 能夠忽略
local iterator 
function allwords()
   local state = {line = io.read(), pos = 1}
   return iterator, state
end

function iterator(state)
    while state.line do -- 若爲有效行的內容就進入循環
        -- 搜索下一個單詞
        local s, e = string.find(state.line, "%w+", state.pos)
        if s then -- 找到一個單詞
            state.pos = e + 1
            return string.sub(state.line, s, e)
        else -- 沒有找到單詞
            state.line = io.read() -- 嘗試讀取下一行
            state.pos = 1
        end
    end
    return nil
end
錯誤記錄
  1. 這裏編碼時犯了一個錯誤,沒找到單詞時使用的是函數定義 io.read ,而不是函數調用 io.read()
  2. 因此會報錯 bad argument #1 to 'find' (string expected, got function)
  3. 意爲第一個參數指望得到 string 類型,實際上獲得的確實 function 類型
  4. 由於輸入的第一行確定會有單詞,因此不會進入 else 讀取下一行
  5. 而打印出第一行的全部單詞後,就不會嘗試讀取輸入了,由於 string.find(state.line, ...) 其中的 第一個參數已經爲 function 類型了,因此循環結束
  6. io.read() 用戶輸入任何東西都會爲 string 類型
  7. 除非指定輸入 io.read("*number") 這樣就指定用戶輸入爲 number 類型了

與無狀態迭代器的對比

  1. 無狀態迭代器將全部狀態保存在 for 變量中
  2. 無需再開始一個循環時建立任何對象
  3. 基於 closure 實現的 table 比一個使用 table 的迭代器高效
  4. 由於訪問 「非局部變量」要比訪問 table

真正的迭代器

  1. 迭代器沒有作實際的迭代,真正作迭代的是 for 循環
  2. 迭代器只是爲每次迭代提供成功後的返回值
  3. 準確地稱呼應爲「生成器」

在迭代器中作實際的迭代操做

  1. 無需寫循環
  2. 須要描述每次迭代時所需執行的動做或行爲的參數,即參數爲某個函數
  3. 迭代器接受一個函數做爲參數,並在其內部循環中調用這個函數
function allwords(f)
    for line in io.read() do
        -- gmatch 匹配全部符合模式的字符串
        for word in string.gmatch(line, "%w+") do
            f(word)
        end
    end
end

allwords(print)
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)

迭代器與生成器的對比

相同點

  1. 開銷一致
  2. 每次迭代都有一次函數調用

不一樣點

迭代器

  1. return 語句只能從匿名函數中返回
  2. 不能從作迭代的函數中返回

生成器

  1. 生成器容許兩個或多個並行的迭代過程git

    1. 逐個單詞的比對兩個文件,需同時遍歷兩個文件
  2. 且可在迭代體中使用 breakreturn 語句
    本篇文章由一文多發平臺ArtiPub自動發佈
相關文章
相關標籤/搜索