麻豆小视频在线观看_中文黄色一级片_久久久成人精品_成片免费观看视频大全_午夜精品久久久久久久99热浪潮_成人一区二区三区四区

首頁 > 開發 > 綜合 > 正文

深入解讀Lua中迭代器與泛型for的使用

2024-07-21 23:05:01
字體:
來源:轉載
供稿:網友

泛型for原理

迭代器是一種可以遍歷集合中所有元素的機制,在Lua中通常將迭代器表示為函數,每調用一次函數,就返回集合中“下一個”元素。每個迭代器都需要在每次成功調用之間保持一些狀態,這樣才能知道它所在的位置及如何步進到下一個位置,closure就可以完成此項工作。下面的示例是列表的一個簡單的迭代器:

function values(t) local i = 0 return function() i = i + 1; return t[i] endend

循環調用:

t = {10, 20, 30}iter = values(t)while true do local el = iter() if el == nil then break end print(el)end

泛型for調用

for el in values(t) do print(el) end

泛型for為一次迭代循環做了所有的簿記工作。它在內部保存了迭代器函數,并在每次迭代時調用迭代器,在迭代器返回nil時結束循環。實際上泛型for保存了3個值:迭代器函數f、恒定狀態s、控制變量a。for做的第一件事就是對in后面的表達式求值,并返回3個值供for保存;接著for會以s和a來調用f。在循環過程中控制變量的值依次為a1 = f(s, a0),a2 = f(s, a1),依次類推,直至ai為nil結束循環。

先看一段代碼

for element in list_iter(t) do  print(element) end 

在不往下看之前,我們可以先試圖根據我們已有的知識結構去理解這段代碼。如果這樣,list_iter(t)應該返回一個類似集合的東西,而我們已經知道實際上只返回了一個匿名函數,也就是迭代器。當然,每次調用迭代器都可以得到一個元素,迭代器的所有的結果倒是可以看成一個集合。因素齊了,我們需要一個邏輯上的解釋,這個邏輯就是 泛型for的語義。
先看文法規定:

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

整個過程是這樣的:
首先,初始化,計算 in 后面表達式的值,表達式應該返回 泛型for 需要的三個值:迭代函數、狀態常量、控制變量;與多值賦值一樣,如果表達式返回的結果個數不足三個會自

動用nil 補足,多出部分會被忽略。
第二,將狀態常量和控制變量作為參數調用迭代函數(注意:對于 for 結構來說,狀態常量沒有用處,僅僅在初始化時獲取他的值并傳遞給迭代函數)。

第三,將迭代函數返回的值賦給變量列表。
第四,如果返回的第一個值為 nil 循環結束,否則執行循環體。
第五,回到第二步再次調用迭代函數。

更具體地說:

for var_1, ..., var_n in explist do block end 

等價于

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 

 泛型 for 在自己內部保存三個值:迭代函數、狀態常量、控制變量。

迭代器的狀態

無狀態的迭代器本身不保存任何狀態,for循環只會用恒定狀態和控制變量來調用迭代器函數。這類迭代器典型例子就是ipairs,下面是ipairs的Lua實現:

local function iter(s, i) i = i + 1 local v = s[i] if v then return i, v endendfunction ipairs(s) return iter, s, 0end

當for循環調用ipairs(list)時,會獲得3個值,然后Lua調用iter(list, 0)得到list, list[1],調用iter(list, 1)得到list, list[2],知道得到一個nil為止。

雖然泛型for只提供一個恒定狀態和一個控制變量用于狀態的保存,但有時需要保存許多其他狀態。這時可以用closure來保存,或者將所需的狀態打包為一個table,并保存在恒定狀態中。

閉包、迭代器和泛型for

到現在,Lua為我們準備了三塊積木:閉包、泛型for和迭代器。一個循環,我們可以利用閉包+迭代器,也可以使用泛型for+迭代器。那我們該怎么取舍呢?Lua也給出了建

議。

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  for i, v in ipairs(a) do  print(i, v) end 

這種情況是Lua最推薦的,迭代器不依賴upvalue,不產生閉包,狀態常量和控制變量借助泛型for保存,通過迭代器的參數傳遞給了迭代器。
再給一個書中的例子:

local iterator -- to be defined later  function allwords()  local state = {line = io.read(), pos = 1}  return iterator, state end  function iterator (state)  while state.line do -- repeat while there are lines   -- search for next word   local s, e = string.find(state.line, "%w+", state.pos)   if s then -- found a word?    -- update next position (after this word)    state.pos = e + 1    return string.sub(state.line, s, e)   else -- word not found    state.line = io.read() -- try next line...    state.pos = 1 -- ... from first position   end  end  return nil -- no more lines: end loop end 

這樣好不好呢,Lua給的答案是否定的。書中有一段話說得很清楚:
我們應該盡可能的寫無狀態的迭代器,因為這樣循環的時候由for 來保存狀態,不需要創建對象花費的代價小;如果不能用無狀態的迭代器實現,應盡可能使用閉包;盡可能不

要使用table 這種方式,因為創建閉包的代價要比創建table 小,另外Lua 處理閉包要比處理table 速度快些。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 国产三级精品最新在线 | 日韩美香港a一级毛片免费 欧美一级淫片007 | 水多视频在线观看 | 久久久久久久免费看 | 久久精品视频69 | av懂色 | 色污视频在线观看 | 久久久成人精品视频 | cosplay裸体福利写真 | 国产69精品久久久久久 | av电影网站在线 | 综合97| 免费国产人成网站 | 午夜丰满少妇高清毛片1000部 | 毛片在线免费播放 | 欧美成人免费电影 | 99精品在线免费 | 久久艹一区 | 欧美亚洲国产一区二区三区 | 毛片午夜 | 99视频有精品视频高清 | 欧美日韩手机在线观看 | 国产成人自拍小视频 | 日韩黄网站 | 精品国产91久久久久 | 国产乱子视频 | 91精品国产91久久久久久蜜臀 | 国产亚洲精品久久久闺蜜 | 久久久久久久久久久久网站 | 国产一区二区三区视频在线观看 | 欧美特一级片 | 正在播放91 | 欧美精品黄色 | 日韩欧美中文字幕视频 | 欧美国产一区二区三区 | 欧洲成人在线视频 | 中文日韩在线视频 | 牛牛a级毛片在线播放 | 好吊色欧美一区二区三区四区 | 欧美69free性videos | 欧美高清另类自拍视频在线看 |