範性for語義以及pair和ipairs的區別

詳情參考 lua手冊數組

1. 範性for語義閉包

在瞭解pair和ipair前先簡單瞭解下lua中的for循環,這裏只闡述範性for循環的語義,範性 for 在本身內部保存迭代函數,實際上它保存三個值:迭代函數、狀態常量、控制變量。for的範式以下函數

for <var-list> in <exp-list> do
 <body> 
end

<var-list>是以一個或多個逗號分隔的變量名列表,<exp-list>是以一個或多個逗號分隔的表達式列表,一般狀況下 exp-list 只有一個值:迭代函數的調用。lua

for k, v in pairs(t) do
 print(k, v) end

  首先,初始化,計算 in 後面表達式的值,表達式應該返回範性 for 須要的三個值:迭代函數、狀態常量、控制變量;與多值賦值同樣,若是表達式返回的結果個數不足三個會自動用 nil 補足,多出部分會被忽略。spa

  第二,將狀態常量和控制變量做爲參數調用迭代函數(注意:對於 for 結構來講,狀態常量沒有用處,僅僅在初始化時獲取他的值並傳遞給迭代函數)。code

  第三,將迭代函數返回的值賦給變量列表。blog

  第四,若是返回的第一個值爲 nil 循環結束,不然執行循環體。索引

  第五,回到第二步再次調用迭代函數。three

2. ipair函數ip

無狀態的迭代器是指不保留任何狀態的迭代器,所以在循環中咱們能夠利用無狀態迭代器避免建立閉包花費額外的代價。每一次迭代,迭代函數都是用兩個變量(狀態常量和控制變量)的值做爲參數被調用,一個無狀態的迭代器只利用這兩個值能夠獲取下一個元素。這種無狀態迭代器的典型的簡單的例子是 ipairs,他遍歷數組的每個元素。

a = {"one", "two", "three"} for i, v in ipairs(a) do
  print(i, v) end

function iter (a, i)   i = i + 1 
  local v = a[i]   if v then
    return i, v   end 
end 

function ipairs (a)   return iter, a, 0 
end

在上面的代碼中,ipairs函數返回三個值,迭代函數爲iter,a爲狀態常量,控制變量的初始值爲0,這三者由for語義保存,每次調用迭代函數iter返回表中的key和value,即 i 和 v 的值,能夠看到,在pair中,只能遍歷有數字索引的元素。若是出現以下圖的狀況,會沒法遍歷全部數字索引元素。

 

 

 

 

 

 

 

 

 

3. pair函數

ipair函數主要由lua的內置函數next實現,next原型大體爲 next (table [, index])。它容許程序遍歷表的全部字段。它的第一個參數是一個表,它的第二個參數是該表中的索引。 next返回表的下一個索引及其關聯值。當使用nil做爲其第二個參數調用時, next返回初始索引及其關聯值。使用最後一個索引調用時,或者在空表中使用nil時, next返回nil。若是第二個參數不存在,則將其解釋爲nil。此外你可使用next(t)檢查表是否爲空。pair有兩種形式,以下。

function pairs (t)   return next, t, nil
end

for k, v in next, t do   ... end

4. 總結

  • 範性for語義是將for循環中 in 後面的表達式進行求值,獲取到狀態常量,迭代函數以及控制變量,而後將狀態常量和控制變量傳入迭代函數中求的key和value的值返回給for循環中的變量列表,直到第一個變量爲nil時中止循環。其中狀態常量一般指表,控制變量即遍歷的步長。
  • pair能夠遍歷一個table的全部元素,而ipair只能遍歷數字索引的元素,此外,若是索引不是連續的ipair會沒法遍歷全部索引
  • pair是由next函數實現的,next函數能夠用來判斷一個表是否爲空, 即判斷 next(t) == nil
相關文章
相關標籤/搜索