最近在看lua,看到泛型for一脸懵逼,完全不知道究竟是怎么运转的,今天拿一个常见的例子来跟大家讲个透彻!!!
泛型 for 的执行过程:
(1) in 后面表达式应返回:迭代函数、状态常量、控制变量; 如果表达式返回的结果个数不足三个会自动用 nil 补足,超出三个的会被忽略。
(2) 向 迭代函数 传入两个参数 状态常量、控制变量 ,迭代函数的第一个返回值 如果为nil ,则停止循环 ; 否则第一个返回值 赋值给 控制变量 ,再次循环调用迭代函数
function square(N,j)
if j<N
then
j = j+1
return j, j*j
end
end
-- 迭代函数、状态常量、控制变量
for i,v in square, 3, 0
do
print(i,v)
end
打印结果:
按照执行规则,我们来分析一下上述代码:
(1) in 后面表达式应返回:迭代函数 square、状态常量 3、控制变量 0;
(2) 向 迭代函数square 传入两个参数 状态常量 3、控制变量0 ,
第一次调用迭代函数返回1 , 1*1 (两个值分别赋值给i,v) ,第一个返回值1 不为nil ,则将第一个返回值 赋值给 控制变量(由0变为1)
再次循环调用迭代函数,状态常量 3、控制变量1 , 迭代函数返回2 , 2*2 (两个值分别赋值给i,v) ,第一个返回值2 不为nil ,则将第一个返回值 赋值给 控制变量(由1变为2)
再次循环调用迭代函数,状态常量 3、控制变量2 , 迭代函数返回3 , 3*3 (两个值分别赋值给i,v) ,第一个返回值3 不为nil ,则将第一个返回值 赋值给 控制变量(由2变为3)
再次循环调用迭代函数,状态常量 3、控制变量3 , 迭代函数不返回,则为nil (两个值分别赋值给i,v) ,第一个返回值nil,停止循环。
for V1, ... ,Vn in 表达式
do
语句...
end
-- 就等价于以下代码:
local _f , _c , _i = 表达式返回的 迭代器函数、恒定状态、控制变量的初值
while true do
local R1, ..., Rn = _f(_c, _i)
_i= R1
if R1 == nil then break end
语句
end
end
了解了上面的原理,我们来看下面的简写例子就容易理解了
--迭代器工厂函数
function iterCreater(a)
local i= 1
--返回一个closure用来保存 i 的值
return
function( )
e =a[i]
i=i+1
return e
end
end
t={ 1,2,3,4,5 }
for r in iterCreater(t) do
print(r)
end
按照执行规则,我们来分析一下上述代码:
(1) in 后面表达式返回(只有一个返回值,所以后面两个为nil):迭代函数 (无名称)、 状态常量 nil、控制变量初值 nil;
(2) 向 迭代函数 (无名称) ,这个函数无需参数,
第一次调用 迭代函数 i=1,返回1 (赋值给r) ,第一个返回值1 不为nil ,则将第一个返回值 赋值给 控制变量(由nil变为1)
再次循环调用迭代函数,状态常量 nil、控制变量1 , i=2,迭代函数返回2 (赋值给r) ,第一个返回值2 不为nil ,则将第一个返回值 赋值给 控制变量(由1变为2)
再次循环调用迭代函数,状态常量 nil、控制变量2 , i=3,迭代函数返回3 (赋值给r) ,第一个返回值3 不为nil ,则将第一个返回值 赋值给 控制变量(由2变为3)
...
再次循环调用迭代函数,状态常量 nil、控制变量6 ,i=6,迭代函数返回nil (赋值给r) , 第一个返回值nil,停止循环。
例子中因为不需要状态常量,所以 表达式只返回了 迭代函数, 状态常量 、控制变量初值 就默认为nil了
我们将上面的例子改造下,表达式也按规则返回三个值(后面的111,222其实没什么用,只是为了打印印证规则)
--迭代器共厂函数
function iterCreater(a)
local i= 1
--返回一个closure用来保存 i 的值
return
function( x,y)
print("x:".. x , "y:"..y)
e =a[i]
i=i+1
return e
end ,111,222
end
t={ 1,2,3,4,5 }
for r in iterCreater(t) do
print(r)
end
打印结果
按照执行规则,我们来分析一下上述代码:
(1) in 后面表达式返回三个值:迭代函数 (无名称)、 状态常量 111、控制变量初值 222;
(2) 向 迭代函数 (无名称) 传入两个参数 , 状态常量 111、控制变量初值 222,
第一次调用 迭代函数 ,(迭代函数打印111, 222 ), i=1 ,返回1 (赋值给r) ,第一个返回值1 不为nil ,则将第一个返回值 赋值给 控制变量(由222变为1)
再次循环调用迭代函数,状态常量 111、控制变量1 , (迭代函数打印111, 1 ), i=2, 迭代函数返回2 (赋值给r) ,第一个返回值2 不为nil ,则将第一个返回值 赋值给 控制变量(由1变为2)
再次循环调用迭代函数,状态常量111、控制变量2 , (迭代函数打印111, 2 ), i=3,迭代函数返回3 (赋值给r) ,第一个返回值3 不为nil ,则将第一个返回值 赋值给 控制变量(由2变为3)
...
再次循环调用迭代函数,状态常量 111、控制变量5 , (迭代函数打印111,5 ), i=6, 迭代函数返回nil (赋值给r) , 第一个返回值nil,停止循环。