您的位置:首页 > 编程语言 > Lua

Lua学习笔记-迭代器和泛型for

2016-02-15 14:22 567 查看
使用迭代器例子:

--list迭代器,返回list中
function values( t )
local i = 0;
local n = table.getn(t)--table中元素个数
--print(n)--打印出表中元素的个数
return function() i = i + 1
return t[i]
end
end
tb = {11,22,33, 44, 55, 66}
--while方式调用
iter = values(tb)--创建闭包变量的参数为函数参数
while true do
local element=iter()--调用闭包时的参数为匿名函数的参数
if element == nil then break
end
print(element)
end
--for的方式
for v in values(tb) do
print(v)
end
泛型for簿记(bookkeeping)所有迭代循环,首先调用迭代工厂,并内部保存迭代函数。每次迭代时调用新的迭代函数。但迭代器返回nil循环结束。

上面使用while的时候,其迭代器有个瑕疵:每次循环时需要创建一个新的闭包,而不能运用之前已经创建好了的closure变量,如果在这个循环外再加一个循环进行迭代时,这就成了一个很繁琐并且容易出错的问题。

创建闭包是需要代价的,只是大部分情况下都没问题,然而有些情况却是不能容忍这个代价的。这时的解决方法是使用泛型for。泛型for本身保存迭代状态,包括迭代函数,状态常量,控制变量,因此不必付出闭包的代价,称这种迭代器为无状态迭代器。

泛型for的语法:

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

<body>

end

<var-list>是变量列表,我们称变量列表中的第一个变量为控制变量,其值为nil时循环结束

<exp-list>是表达式列表,通常<exp-list>只有一个值:迭代工厂的调用

执行过程:

1.初始化迭代函数,计算in后面表达式的值,表达式应该返回泛型for需要的3个值:迭代函数、状态常量、控制变量,与多值赋值一样,如果表达式返回的结果个数不足3个会自动用nil补足,多出部分则忽略。

2.将状态常量和控制变量作为参数调用迭代函数(注意:对于for结构来说,状态常量没有用处,仅仅在初始化时获取他的值并传递给迭代函数)。

3.将迭代函数返回的值赋给变量列表。

4.如果返回的第一个值为nil,则循环结束,否则执行循环体。

5.回到第2步。

更准确地说:

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都创建一个新的closure变量了。
function iterNew(a,i)
i=i+1
if a[i]==nil then
return nil,nil
else return i,a[i]
end
end

function ipairsnew(a)--该定义和ipairs是一样的,此处为了避免
return iterNew,a,0--iterNew在这里只是一个函数变量,并不是调用函数
end

a={"one","two","three",'4'}
for i,v in ipairsnew(a) do
print(i,v)
end
print("Defined by Lua:")
for i,v in ipairs(a) do--ipairs是Lua中已经定义的,与上述我们定义的ipairsnew其实是完全相同的。
print(i,v)
end
print('use while instead of for')
--泛型for修改为while方式
do
local _it,_s,_k=ipairs(a)
while true do
k,v=_it(_s,_k)
_k=k
if k==nil then break end
print(k,v)
end
end
--遍历文件中的所有匹配的单词
如果迭代函数是f,状态常量是s,控制变量的初始值为a0,那么控制变量将循环:a1=f(s,a0),a2=f(s,a1),....直到ai=nil

注明:标准库提供了几种迭代器,包括用于迭代文件中每行的(io.lines)、 迭代 table 元素的(pairs)、迭代数组元素的(ipairs)、迭代字符串中单词的(string.gmatch)。注意各自的使用场景。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: