本篇主要是记录了小编在学习lua程序设计中关于泛型for和迭代器的内容的理解和遇到的问题。
迭代器
迭代器:就是一种可以遍历一种集合中所有的元素的机制(例如C++中的foreach等),并且每次调用函数,返回集合中的“以一个”元素。为了能够实现这目的,因此每个迭代器都需要在每次成功调用之间保持一些状态。恰好,closure通常就是解决这些而产生的。closure就是一种可以访问其外部嵌套环境中的局部变量的函数。
function values(t) --values是创建该closure的工厂函数
local i = 0
return function() --function()函数就是一个closure
i = i + 1
return t[i] --closure将它的状态保存在其外部变量i、t中
end
end
泛型for
提出背景:由于上面的迭代器生成方式有一个严重的缺点,在每次循环调用时都会创建一个新的closure,产生了一些开销;因此,通过for的自身来保存迭代器的状态,这些状态有迭代器函数、恒定状态、控制变量。
for <var_list> in <exp_list> do --var_list:变量列表;exp_list:表达式列表
--body
end
for做的第一件事就是对in后面的表达式求值,并且在对表达式求值的过程中,表达式会返回三个值分别是迭代函数、恒定状态、控制变量的初值,并且这三个值会被for保存。a={12,13}
local function iter(m, i)
i = i +1
local v = m[i]
if v then
return i, v
end
end
function ipa(a) --ipa就是就是表达式
return iter, a, 0 --返回迭代函数、恒定状态(a)、控制变量初值
end
泛型for:
for i, v in ipa(a) do
print(i, v)
end
重点:对for循环处理过程分解:
do
local _f,_s,_var = ipa(a) --分别是iter,a,0
while true do
local _var1,_var2 = _f(_s,_var) --返回的是上面i,v(1,a[1])
_var = _var1 --控制变量为1
if _var==nil then --当迭代器函数的第一个返回值为nil,跳出循环
break
end
<block> --每次循环的操作(如:上面的print(i,v))
end
end
输出测试:
1 12
2 13
为了验证上面的说法,下面我们直接采用for循环将其输出:
for i=1, 2,1 do
t,m,n = ipa(a)
print(t(a,0))
print(m,n)
end
输出结果:
1 12 --print(t(a,0))
table: 00D43098 0 --print(m,n)
1 12
table: 00D43098 0
小结:
通过上面程序,可以发现我们的迭代器函数iter并没有创建closure,因此通过for循环调用迭代器函数发现每次输出的内容是一样的。因此主要的迭代工作是落在了泛型for的上面。