迭代器與泛型 for 3
具備複雜狀態的迭代器
- 使用
closure
能夠保存迭代器所需保存的全部狀態 - 也能夠將迭代器所需的全部狀態打包爲一個
table
並保存在 恆定狀態中 - 在循環過程當中 恆定狀態 老是同一個
table
- 但這個
table
的內容卻能夠改變即在循環過程當中改變table
數據 - 因爲這種迭代器能夠保存全部數據將其存儲到 恆定狀態中,所以第二個參數 控制變量 能夠忽略
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
錯誤記錄git
- 這裏編碼時犯了一個錯誤,沒找到單詞時使用的是函數定義
io.read
,而不是函數調用io.read()
- 因此會報錯
bad argument #1 to 'find' (string expected, got function)
- 意爲第一個參數指望得到
string
類型,實際上獲得的確實function
類型 - 由於輸入的第一行確定會有單詞,因此不會進入 else 讀取下一行
- 而打印出第一行的全部單詞後,就不會嘗試讀取輸入了,由於
string.find(state.line, ...)
其中的 第一個參數已經爲function
類型了,因此循環結束 io.read()
用戶輸入任何東西都會爲string
類型- 除非指定輸入
io.read("*number")
這樣就指定用戶輸入爲number
類型了
與無狀態迭代器的對比
- 無狀態迭代器將全部狀態保存在
for
變量中 - 無需再開始一個循環時建立任何對象
- 基於
closure
實現的table
比一個使用table
的迭代器高效 - 由於訪問 「非局部變量」要比訪問
table
快
真正的迭代器
- 迭代器沒有作實際的迭代,真正作迭代的是
for
循環 - 迭代器只是爲每次迭代提供成功後的返回值
- 準確地稱呼應爲「生成器」
在迭代器中作實際的迭代操做
- 無需寫循環
- 須要描述每次迭代時所需執行的動做或行爲的參數,即參數爲某個函數
- 迭代器接受一個函數做爲參數,並在其內部循環中調用這個函數
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)
迭代器與生成器的對比
相同點
- 開銷一致
- 每次迭代都有一次函數調用
不一樣點
迭代器
- return 語句只能從匿名函數中返回
- 不能從作迭代的函數中返回
生成器
- 生成器容許兩個或多個並行的迭代過程
- 逐個單詞的比對兩個文件,需同時遍歷兩個文件
- 且可在迭代體中使用
break
和return
語句
本篇文章由一文多發平臺ArtiPub自動發佈