Lua中無狀態和有狀態迭代器之間有什麼區別?請詳細解釋?我們何時需要使用無狀態和何時使用無狀態?我需要例子來理解這個概念。Lua中有狀態和無狀態迭代器之間的區別
回答
首先讓我們商定一個定義:(在Lua中)一個迭代器是一個函數 -like對象,每次調用時它都會返回一個序列中的下一個值。我認爲它有助於改寫for
迭代因爲做的是Lua的參考手冊:
for itemlist in expression do block end
是邏輯上等同於(僞):
do
local func, seq, controlVar = expression
while true do
local itemlist = func(seq, controlVar)
if first of itemlist == nil then break end
controlVar = first of itemlist
block (which uses items in itemlist)
end
end
其中expression
是數據的三重(或函數調用返回這樣的三重峯):
func
是實際的迭代函數seq
被遍歷controlVar
序列是循環控制變量
迭代狀態可能需要找到序列中的下一個項目上迭代的任何狀態。因此無狀態迭代器是func
不包含任何這樣的狀態:您可以隨時調用func(seq, controlVar)
,返回值將始終相同(如果seq未更改);它不取決於通話之前發生的事情。
如上所示,Lua支持一個循環控制變量。所以爲了讓一個序列可以通過無狀態迭代器迭代,必須有可能根據一個循環控制變量來確定序列中的下一個項目。也就是說,只能從「(s,controlVar)」中找出「下一個項目」。 ipairs()
生成一個迭代器:ipairs(s)
返回三元組(iterFunction, s, 1)
;可以給出iterFunction
和s
和索引1,並且返回2, s[1]
,然後3, s[2]
等(最終nil, s[N]
用於N個項目的表格)。
如果發現序列中的下一個項目需要多個循環控制變量,該怎麼辦?還是取決於其他變量的狀態,在迭代過程中應該保存這些變量?例如:
- 一個無盡的迭代器可能需要跟蹤「第一個」項目,以便一旦達到序列的末尾,它就可以在第一個項目處恢復;
- 圖迭代器可能需要在深度優先搜索中跟蹤「最近的同胞」,以便一旦到達分支的末尾,它就可以繼續下一個最近的同胞。
有狀態迭代器持有有關迭代的狀態,以便可以找到下一個項目。在Lua中,如果迭代器函數是閉包(具有upvalues的函數)或仿函數(表的行爲如函數,即具有__call
元方法),則這是可能的。 up值(閉包)或數據成員(函子)可以存儲所需的狀態。
無狀態迭代器總是可以包裝到有狀態迭代器中。對於ipairs
:
function statefulIpairs(s)
local f, s, var = ipairs(s)
return function()
local i, v = f(s,var)
var = i
return i, v
end
end
這可以被稱爲
tbl = {'a', 'b', 'c', 'd'}
sip = statefulIpairs(tbl) -- sip is stateful iter specific to tbl
for i,v in sip() do print(i,v) end
有狀態迭代的開發人員決定哪些功能迭代器有:迭代器的API可允許退,反轉方向,或其他操作。這甚至可以在關閉的情況下使用:可以使用附加參數來訪問附加功能。例如,接受第三個參數,當非爲零,重置序列的開端:
function resetableStatefulIpairs(s)
local f, s, var = ipairs(s)
local start = var
return function(a,b,reset)
if reset ~= nil then var = start; return end
local i, v = f(s,var)
var = i
return i, v
end
end
sip = resetableStatefulIpairs(tbl) -- sip is stateful iter specific to tbl
for i,v in sip() do print(i,v) end
sip(nil, nil, true) -- reset it
for i,v in sip() do print(i,v) end
更新了一個更簡潔的例子是如何產生的功能迭代器,接受命令,這樣你可以」 ...停止在序列的其餘部分的序列中的任意位置和迭代的3倍」(由@deduplicator的要求):
function iterGen(seq, start)
local cvar = start or 1
return function(cmd)
if cmd == nil then
if cvar > #seq then return nil, nil end
val = seq[cvar]
cvar = cvar + 1
return cvar-1, val
else
cmd = cmd[1]
if cmd == 'rewind' then
cvar = start or 1
elseif cmd == 'newstart' then
start = cvar
end
end
end
end
通過以上:
> s = {1,2,3,4,5,6,7}
> iter = iterGen(s)
> for i,v in iter do print(i,v); if i==3 then break end end
1 1
2 2
3 3
> iter {'newstart'} -- save current as the new start pos
> for i,v in iter do print(i,v) end -- continue till end
4 4
5 5
6 6
7 7
> iter {'rewind'}
> for i,v in iter do print(i,v) end
4 4
5 5
6 6
7 7
> iter {'rewind'}
> for i,v in iter do print(i,v) end
4 4
5 5
6 6
7 7
正如所證明的,除了迭代狀態在迭代器內部這一事實之外,狀態迭代器沒有什麼特別之處,因此,如上所述,開發人員需要公開所需的功能,如上面的rewind和newstart。使用無狀態迭代器,沒有限制。
這將是一個更自然的API設計迭代器作爲函子,因爲然後迭代器「函數」有「方法」可以調用,但創建一個可指令函數是一個有趣的挑戰。
狀態和無狀態的迭代器之間的區別很簡單:
有狀態的迭代器有內部狀態,所以你不能創建它們,運行它們了一下,然後反覆要求使用相同的迭代器序列的末端。 string.gmatch(...)
返回一個很好的例子。
相反,無狀態迭代器是其輸入的純函數,所有狀態都是外部的。最有名的是返回pairs(a)
(返回a, next
,如果沒有__pairs
metamethod定義)和ipairs
(如果沒有`__ipairs metamethod)。如果你想重複遍歷序列的末尾,只保存參數。
有趣,但我不明白這:)有狀態的迭代器_cannot_重複請求的序列結束?你能舉一個例子,說明你可以用'gmatch'做什麼,如果它是無狀態的而不是有狀態的?另外,你怎麼知道'gmatch'是有狀態的?如果你可以擴大你的答案(而不是評論),那將非常感激。 – Schollii
看看lua文檔中有關string.gmatch的第一句話(版本5.2)。 – Deduplicator
AFAICT(來自測試),即使沒有引用留給字符串(因此函數中存在引用),也可以從'gmatch'中存儲返回的函數並在將來隨時調用它。 – Schollii
- 1. 無狀態和有狀態壓縮之間的區別?
- 2. 狀態圖和有限狀態機(FSM)之間的區別?
- 3. ACTIVE和NORMAL狀態之間的區別
- 4. 視圖狀態和控制狀態之間的區別
- 5. 有狀態迭代器Java
- 6. 無狀態和有狀態小部件有什麼區別?
- 7. 有狀態和無狀態lambda表達式有什麼區別?
- 8. 線程狀態之間的區別
- 9. 下面的Lua迭代器是無狀態的嗎?
- 10. http響應狀態代碼402和403之間的區別
- 11. lua_xmove在不同的lua狀態之間
- 12. 會話bean和實體bean以及有狀態會話bean和無狀態會話bean之間的區別
- 13. Angular docs:如何在控制器之間共享無狀態/有狀態代碼?
- 14. 迭代模型和無狀態環境
- 15. 無狀態和有狀態系統之間有什麼區別,它們如何影響並行性?
- 16. SCXML狀態圖和UML狀態圖有什麼區別?
- 17. Lua和C++中的有限狀態機
- 18. 將狀態綁定到屬性的[]和{{}}之間的區別?
- 19. 有狀態和無狀態流處理
- 20. Vistor模式和狀態模式之間的區別?
- 21. MEM_RESERVE和MEM_COMMIT狀態之間的確切區別是什麼?
- 22. Facebook FQL:狀態表和流表之間的區別?
- 23. AngularJS ui.router視圖屬性和子狀態之間的區別?
- 24. github API提交狀態「失敗」和「錯誤」之間的區別?
- 25. 狀態xxxServerHandle和unstateful yyyServerhandle之間的區別?
- 26. 可靠的服務無狀態和有狀態服務之間的通信
- 27. 計算狀態Chages和狀態之間的時間
- 28. UML中活動圖的狀態和活動之間有什麼區別?
- 29. 是否有事件和狀態之間有任何明顯的區別
- 30. lua和env lua之間的區別?
非常感謝你,我感謝你的回答,否則解釋它像我這樣的noob真的很難:)謝謝:) –
@Simrankaur很高興這對你有意義。既然你有足夠的積極點,你應該嘗試提出答案或評論什麼是不明確的,如果作者可以修復 - 這提高了SO質量。乾杯! – Schollii