先代表,我是個正在學習 Lua 的新手,在遇到些學習上的問題,通過思考嘗試,讓後寫下我對相關問題知識的認識。
個人博客:https://crabsaberv.github.io/html
從菜鳥教程上學習 Lua 迭代器過程當中,遇到了些障礙。雖然根據菜鳥教程中的解釋:git
下面咱們看看泛型 for 的執行過程:github
- 首先,初始化,計算 in 後面表達式的值,表達式應該返回泛型 for 須要的三個值:迭代函數、狀態常量、控制變量;與多值賦值同樣,若是表達式返回的結果個數不足三個會自動用 nil 補足,多出部分會被忽略。
- 第二,將狀態常量和控制變量做爲參數調用迭代函數(注意:對於 for 結構來講,狀態常量沒有用處,僅僅在初始化時獲取他的值並傳遞給迭代函數)。
- 第三,將迭代函數返回的值賦給變量列表。
- 第四,若是返回的第一個值爲nil循環結束,不然執行循環體。
- 第五,回到第二步再次調用迭代函數
可是在本身更具理解,試着編寫一些測試 Lua 無狀態迭代器代碼時,出現的結果卻讓人捉急。
可先閱覽 Lua 官方文檔中對迭代器的描述: Lua 5.3 文檔 -3.3.5
(能看懂官方解釋,基本上本文就沒必要往下看了)shell
開始根據菜鳥教程編寫了一個無狀態迭代器,固然運行結果也正常。閉包
function square(iteratorMaxCount,currerntNumber) if currerntNumber < iteratorMaxCount then currerntNumber = currerntNumber+1; return currerntNumber,currerntNumber*currerntNumber; end end for i,n in square,10,0 do print(i,n) end
這段代碼的行爲其實很簡單,就是打印了10之內全部的平方數。
根據菜鳥教程描述的 for 的執行過程可知,suqare 就是迭代器函數,10是狀態常量,0則是控制變量。而當運行時,會先根據 square 以及參數,獲得迭代器的三個元素(迭代函數,狀態常量,控制變量),之後就會利用這三個元素來進行迭代的過程。函數
但這裏菜鳥教程對這裏有些輕描淡寫,並沒說清楚真正各個參數是如何被使用,尤爲是 square 的參數和返回值之間的聯繫或者是否有聯繫,卻沒講清楚。學習
後來,我在想常常性在 for 中用兩個變量來接收,能不能只用一個 臨時變量來接收迭代結果,而且迭代器函數可否只有一個參數,一個返回值。測試
因而有了下面的代碼:ui
function aa(a) if a<10 then a = a+1 return a end end for i in aa,1 do print(i) end
以我最初對迭代器的理解,應該會執行10次運算,然而:lua
2 2 2 . . .
無限循環打印 2 。
此時就開始納悶了,這個迭代器的內部原理到底是什麼,aa() 被作了,其中的參數 a 又作了什麼處理,返回的 a 除了賦值給了 i,而後又去了哪裏。
爲了解決這些疑問,我嘗試了不少種不一樣的組合形式,好比將參數設置爲2個,返回值設置成多個,參數調換位置等,但不少時候最後的表現結果卻和預期差的很遠。
沒有辦法,百度不給力,那就只能去看 Lua 的官方文檔了。
果不其然,官方的解釋很是好理解,還給了示例。
參照官方文檔-3.3.5的解釋:
for statement like
for var_1, ···, var_n in explist do block end
is equivalent to the code:
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
上面的迭代器遍歷能夠看做是下面的過程:
可見一開始由 do 語句塊將包裹起來,其中會建立三個變量,而這三個變量 f,s,var 正好對應着迭代器三元素:f-迭代器函數,s-狀態常量,var-控制變量。其值由 explist 的返回值得到。這也就證實了爲什麼 for 迭代器 in 後面的最終函數必須以:「迭代器函數,狀態常量,控制變量「 的形式/結構來編寫。
後來在語句塊中編寫一個 while 循環,其內部又用多個局部變量 var_x,來接收 f(s,var) 的結果。而能看出這些 var_x 就是咱們 for 循環中用於接收迭代過程結果的變量。這就構成了一個閉包,f 就是這裏的一個閉包函數。
而下面的語句,將 var_1 接收到的 var 的值又再次賦值給 var。var 是一個外部變量,那麼在下次循環中,f(s,var)
的 var 傳入的就是新值,也便是控制變量的更新。
當 var 爲 nil 時,循環就會跳出。
參考了這些,我認爲對於無狀態迭代器的編寫須要遵照幾個規則:
參照這幾個規則,基本上能保證咱們編寫的無狀態迭代器不會出現什麼超出預期的問題。
而根據分析,也能得出關於迭代器的內部參數特色: