上一篇我們介紹了,可以使用for循環(huán)來完成迭代器的調(diào)用,十分簡潔。
那么,具體這for循環(huán)做了什么呢?我當然沒有去看源碼,我只是看書而已。
資料來源于《Lua程序設(shè)計》第二版,如果這本書的內(nèi)容沒有錯的話,那么,本篇文章理論上也不會有錯~
1.返回兩個值的迭代器
pairs是能遍歷table的key和value的,而我們之前寫的dieDaiQi函數(shù)只能返回value。
所以,我們要改改dieDaiQi函數(shù),如下:
復(fù)制代碼 代碼如下:
function dieDaiQi(t)
local i = 0;
return function()
i = i + 1;
if i > #t then
return nil;
end
return i, t[i];
end
end
當然了,這不是一個安全的迭代器,我們假設(shè)table中沒有nil值。
至于為什么要有一個if i > #t的判斷,待會會說到。
使用如下方式調(diào)用迭代器:
復(fù)制代碼 代碼如下:
local t = {"fdsd", "445", "9999"};
for k, v in dieDaiQi(t) do
print(k .. "," .. v);
end
輸出結(jié)果如下:
復(fù)制代碼 代碼如下:
[LUA-print] 1,fdsd
[LUA-print] 2,445
[LUA-print] 3,9999
2.for .. in .. do的真面目
【for k, v in dieDaiQi(t) do end】這段代碼實際上等價于以下代碼:
復(fù)制代碼 代碼如下:
do
local _f, _s, _var = dieDaiQi(t);
while true do
local k, v = _f(_s, _var);
_var = k;
if _var == nil then
break;
end
print(k .. "," .. v);
end
end
是不是很復(fù)雜?其實它和我們之前第一次調(diào)用迭代器的代碼很像,我們先刪掉復(fù)雜的部分,代碼變成如下:
復(fù)制代碼 代碼如下:
do
local _f = dieDaiQi(t);
while true do
local k, v = _f();
if k == nil then
break;
end
print(k .. "," .. v);
end
end
試試運行這段代碼,結(jié)果如下:
復(fù)制代碼 代碼如下:
[LUA-print] 1,fdsd
[LUA-print] 2,445
[LUA-print] 3,9999
和直接使用for in循環(huán)是一樣的結(jié)果。
實際上,我說的這些都是廢話,因為我們之前就已經(jīng)說,for in循環(huán)就是用來簡化迭代器的調(diào)用的,所以當然是一樣的結(jié)果。
3.迭代器函數(shù)、恒定狀態(tài)、控制變量初值
我們來看看for in真面目的第一句代碼:local _f, _s, _var = dieDaiQi(t);
三個返回值分別代表迭代器函數(shù)(_f)、恒定狀態(tài)(_s)、控制變量初值(_var)。
迭代器函數(shù):就不用解釋了,就是我們的dieDaiQi返回的閉合函數(shù)。
恒定狀態(tài):其實就是一個變量,這個變量一直不變,所以稱之為恒定。
控制變量初值:和恒定相對于的,這是一個會不斷改變的變量。
因為我本人沒有實際使用過這種特性,所以沒法舉出實際的例子,只能從理論上去解釋。
1.比如我們的dieDaiQi函數(shù),它只有一個返回值,就是那個閉合函數(shù),所以,_s和_var都是nil。
2.接著調(diào)用local k, v = _f(_s, _var); 這實際上就是調(diào)用了閉合函數(shù),并且將恒定值和變量值都作為參數(shù)傳遞進去。
3.Lua的函數(shù)是很自由的,即使_f函數(shù)本身沒有參數(shù),也可以傳參數(shù)進去,不會影響什么,所以,兩個nil值傳進去了,沒有任何事情發(fā)生,就像是直接調(diào)用_f()一樣。
4.再下一句代碼:_var = k; 這是把閉合函數(shù)(_f)的第一個返回值保存起來,因為每次調(diào)用閉合函數(shù)(_f)返回值都是下一個迭代值,所以_var每次都是不一樣的值。
5.如果_var的值為nil,則停止循環(huán),結(jié)束迭代。
因此,我們編寫迭代器的時候,迭代結(jié)束的方式就是讓第一個返回值為nil。
那么,如果我們讓dieDaiQi函數(shù)返回恒定狀態(tài)和控制變量初值,又是什么樣的情況呢?
代碼如下:
復(fù)制代碼 代碼如下:
function dieDaiQi(t)
local i = 0;
return function(s, var)
i = i + 1;
if i > #t then
return nil;
end
print("恒定值=" .. s .. ", 變量值=" .. var)
return i, t[i];
end, 10, 0
end
留意一下,dieDaiQi函數(shù)現(xiàn)在會返回三個參數(shù),后面的10和0分別就是恒定狀態(tài)和控制變量初值。
同時,閉合函數(shù)也多了兩個參數(shù):s和var。
于是,我們再次用for循環(huán)遍歷迭代器:
復(fù)制代碼 代碼如下:
for k, v in dieDaiQi(t) do
print(k .. "," .. v);
end
輸出結(jié)果如下:
復(fù)制代碼 代碼如下:
[LUA-print] 恒定值=10, 變量值=0
[LUA-print] 1,fdsd
[LUA-print] 恒定值=10, 變量值=1
[LUA-print] 2,445
[LUA-print] 恒定值=10, 變量值=2
[LUA-print] 3,9999
恒定值自然是一直不變的,而變量值在每一次調(diào)用了閉合函數(shù)之后,就會賦值為k的值,所以變量值一直按著table的key值在變化。
可能一時有點混亂,不過,只要對照著for .. in .. do .. end對應(yīng)的實現(xiàn)代碼,就很好理解了。
4.結(jié)束
終于寫完了,我快撐不住了,一晚上寫兩篇文章,可夠折騰的。
現(xiàn)在眼睛都是花的…我不知道我還能堅持多少個晚上…
幸好學習的內(nèi)容會越來越難,這樣我就沒法一個晚上就理解透徹,也就沒法每晚寫一篇教程了~
太好了,呵呵。(小若:想偷懶就偷懶吧,說這么多做什么)
您可能感興趣的文章:- Lua編程示例(三):稀疏表、雙端隊列、格式化輸出、表和循環(huán)表的格式化輸出
- Lua編程中使用嵌套循環(huán)的使用教程
- Lua中的repeat...until循環(huán)語句使用教程
- 詳解Lua中repeat...until循環(huán)語句的使用方法
- Lua中for循環(huán)語句的使用教程
- 詳解Lua中的while循環(huán)語句的使用
- Lua中數(shù)字for循環(huán)實例
- Lua中變相實現(xiàn)continue跳出循環(huán)
- Lua中三種循環(huán)語句的使用講解