​https://www.jb51.net/article/86840.htm​

泛型for基本格式

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

流程

  1. 首先,初始化,计算 in 后面表达式的值,表达式应该返回 泛型for 需要的三个值:迭代函数、状态常量、控制变量;与多值赋值一样,如果表达式返回的结果个数不足三个会自动用nil 补足,多出部分会被忽略。
  2. 第二,将状态常量和控制变量作为参数调用迭代函数(注意:对于 for 结构来说,状态常量没有用处,仅仅在初始化时获取他的值并传递给迭代函数)
  3. 第三,将迭代函数返回的值赋给变量列表。
  4. 第四,如果返回的第一个值为 nil 循环结束,否则执行循环体。
  5. 第五,回到第二步再次调用迭代函数。

闭包实现ipairs

迭代器是一种可以遍历集合中所有元素的机制,在Lua中通常将迭代器表示为函数,每调用一次函数,就返回集合中“下一个”元素,直到nil结束。
迭代器本身不会接着迭代,要while,for来控制迭代

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

t = {10, 20, 30}

print("循环调用---------------")
iter = values(t)
while true do
local el = iter()
if el == nil then break end
print(el)
end

print("泛型for调用---------------")
for el in values(t) do print(el) end

print("ipair实现原理---------------")
local function iter(s, i)
i = i + 1
local v = s[i]
if v then return i, v end
end
function myipairs(s)
return iter, s, 0
end

for i,v in myipairs(t) do
print(i)
print(v)
end

代码分析:

  1. for第一次调用myipairs(t),生成了3个变量,迭代器iter,状态常量s,控制变量0
  2. 在for的驱动下进行迭代,第一次传入 iter(s,0),返回值给到输出列表i,v
  3. 闭包的作用下i是upvalue,下次传入 iter(s,1)
  4. 持续第3步,传出nil结束for循环

闭包性能问题

闭包会造成变量在内存中持久占用,因此会有一定的性能问题,最好不要轻易使用,即便使用也要在恰当的实际进行释放