【笨木頭Lua專欄】基礎補充04:for迴圈與迭代器的秘密,lua專欄

來源:互聯網
上載者:User

【笨木頭Lua專欄】基礎補充04:for迴圈與迭代器的秘密,lua專欄

上一篇我們介紹了,可以使用for迴圈來完成迭代器的調用,十分簡潔。

那麼,具體這for迴圈做了什麼呢?我當然沒有去看源碼,我只是看書而已。

資料來源於《Lua程式設計》第二版,如果這本書的內容沒有錯的話,那麼,本篇文章理論上也不會有錯~

笨木頭花心貢獻,哈?花心?不,是用心~

轉載請註明,原文地址: http://www.benmutou.com/archives/1717

文章來源:笨木頭與遊戲開發

1.返回兩個值的迭代器

pairs是能遍曆table的key和value的,而我們之前寫的dieDaiQi函數只能返回value。

所以,我們要改改dieDaiQi函數,如下:

 
  1. function dieDaiQi(t)
  2.     local i = 0;
  3.     return function()
  4.         i = i + 1;  
  5.        
  6.         if i > #t then
  7.             return nil;
  8.         end          
  9.         return i, t[i];
  10.     end
  11. end

當然了,這不是一個安全的迭代器,我們假設table中沒有nil值。

至於為什麼要有一個if i > #t的判斷,待會會說到。

 

使用如下方式調用迭代器:

 
  1.     local t = {"fdsd", "445", "9999"};
  2.     for k, v in dieDaiQi(t) do
  3.         print(k .. "," .. v);
  4.     end

輸出結果如下:

[LUA-print] 1,fdsd
[LUA-print] 2,445
[LUA-print] 3,9999

 

2.for .. in .. do的真面目

【for k, v in dieDaiQi(t) do  end】這段代碼實際上等價於以下代碼:

 
  1.     do
  2.         local _f, _s, _var = dieDaiQi(t);
  3.        
  4.         while true do
  5.             local k, v = _f(_s, _var);
  6.             _var = k;
  7.            
  8.             if _var == nil then
  9.                 break;
  10.             end
  11.            
  12.             print(k .. "," .. v);
  13.         end
  14.     end

是不是很複雜?其實它和我們之前第一次調用迭代器的代碼很像,我們先刪掉複雜的部分,代碼變成如下:

 
  1.     do
  2.         local _f = dieDaiQi(t);
  3.        
  4.         while true do
  5.             local k, v = _f();
  6.            
  7.             if k == nil then
  8.                 break;
  9.             end
  10.            
  11.             print(k .. "," .. v);
  12.         end
  13.     end

試試運行這段代碼,結果如下:

[LUA-print] 1,fdsd
[LUA-print] 2,445
[LUA-print] 3,9999

 

和直接使用for in迴圈是一樣的結果。

 

實際上,我說的這些都是廢話,因為我們之前就已經說,for in迴圈就是用來簡化迭代器的調用的,所以當然是一樣的結果。

 

3.迭代器函數、恒定狀態、控制變數初值

我們來看看for in真面目的第一句代碼:local _f, _s, _var = dieDaiQi(t);

三個傳回值分別代表迭代器函數(_f)、恒定狀態(_s)、控制變數初值(_var)。

 

迭代器函數:就不用解釋了,就是我們的dieDaiQi返回的閉合函數。

恒定狀態:其實就是一個變數,這個變數一直不變,所以稱之為恒定。

控制變數初值:和恒定相對於的,這是一個會不斷改變的變數。

 

因為我本人沒有實際使用過這種特性,所以沒法舉出實際的例子,只能從理論上去解釋。

1.比如我們的dieDaiQi函數,它只有一個傳回值,就是那個閉合函數,所以,_s和_var都是nil。

2.接著調用local k, v = _f(_s, _var); 這實際上就是調用了閉合函數,並且將恒定值和變數值都作為參數傳遞進去。

3.Lua的函數是很自由的,即使_f函數本身沒有參數,也可以傳參數進去,不會影響什麼,所以,兩個nil值傳進去了,沒有任何事情發生,就像是直接調用_f()一樣。

4.再下一句代碼:_var = k;  這是把閉合函數(_f)的第一個傳回值儲存起來,因為每次調用閉合函數(_f)傳回值都是下一個迭代值,所以_var每次都是不一樣的值。

5.如果_var的值為nil,則停止迴圈,結束迭代。

 

因此,我們編寫迭代器的時候,迭代結束的方式就是讓第一個傳回值為nil。

 

那麼,如果我們讓dieDaiQi函數返回恒定狀態和控制變數初值,又是什麼樣的情況呢?

代碼如下:

 
  1. function dieDaiQi(t)
  2.     local i = 0;
  3.     return function(s, var)
  4.         i = i + 1;  
  5.        
  6.         if i > #t then
  7.             return nil;
  8.         end        
  9.         print("恒定值=" .. s .. ", 變數值=" .. var)
  10.         return i, t[i];
  11.     end, 10, 0
  12. end

留意一下,dieDaiQi函數現在會返回三個參數,後面的10和0分別就是恒定狀態和控制變數初值。

同時,閉合函數也多了兩個參數:s和var。

 

於是,我們再次用for迴圈遍曆迭代器:

 
  1.     for k, v in dieDaiQi(t) do
  2.         print(k .. "," .. v);
  3.     end

輸出結果如下:

[LUA-print] 恒定值=10, 變數值=0
[LUA-print] 1,fdsd
[LUA-print] 恒定值=10, 變數值=1
[LUA-print] 2,445
[LUA-print] 恒定值=10, 變數值=2
[LUA-print] 3,9999

 

恒定值自然是一直不變的,而變數值在每一次調用了閉合函數之後,就會賦值為k的值,所以變數值一直按著table的key值在變化。

可能一時有點混亂,不過,只要對照著for .. in .. do .. end對應的實現代碼,就很好理解了。

 

4.結束

終於寫完了,我快撐不住了,一晚上寫兩篇文章,可夠折騰的。

現在眼睛都是花的…我不知道我還能堅持多少個晚上…

幸好學習的內容會越來越難,這樣我就沒法一個晚上就理解透徹,也就沒法每晚寫一篇教程了~

太好了,呵呵。(小若:想偷懶就偷懶吧,說這麼多做什麼)

 


Java, 迭代器與for迴圈的問題

因為方法2是錯誤的!你一旦進入
if(!w.isLive)
{
this.fio.getH_gun().remove(w);
}
這塊代碼,就會移掉一個元素,後面的元素會向前移,所有後面的元素的下標會減1,導致接下來的那個元素無法遍曆到
你該成
if(!w.isLive)
{
this.fio.getH_gun().remove(w);
i--;
}
或者迴圈的時候
for(int i=this.fio.getH_gun().size()-1;i>=0; i--)
這樣往前迴圈也是對的

異常肯定會重現,具體原因自己找!
 
for迴圈中有迭代器的話,就不可以定義int i=0了

這不是迭代器的問題吧

同一語句不可以定義兩個變數
任何情況下都不可以 包括你的逗號
這種情況就在外部定義吧
 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.