Lua-基础(四)迭代器

Lua-基础(四)迭代器
fasty迭代器是一种支持指针类型的结构,它可以遍历集合的每一个元素。在 Lua 中我们 常常使用函数来描述迭代器,每次调用该函数就返回集合的下一个元素。常常使用函数来描述迭代器,每次调用该函数就返回集合的下一个元素。
闭包和迭代器
- 迭代器需要保留上一次成功调用的状态
- 迭代器需要保留下一次成功调用的状态
我们知道闭包可以保留每次调用的状态。并且可以方便的访问局部变量;所以我们也可以使用闭包来构建迭代器。
还记得我们在做for循环遍历表时的pairs(t)的迭代器吗?我们尝试自己来写一个迭代器:
1 | -- 迭代器 |
Ps:如果要创建一个闭包必须要创建其外部局部变量。所以一个典型的闭包的结构包含两个函数:一个是闭包自己;另一个是工厂(创建闭包的函数)。
当然我们可以将这个迭代器应用于for循环中:
for value in list_iter(t) do
print(value)
end
迭代器小例子-访问文件
1 | -- 打开文件 |
深入了解for循环
在上面的闭包迭代器中我们不难发现,如果使用for循环则可以免去while循环所需的迭代闭包变量,
这样使用起来就比while循环要方便一些。那for循环是怎么做到的呢?
让我们来看看for循环的格式:for var_1, ..., var_n in explist do block end
在for循环我们可以使用多个参数,如之前我们使用的系统自带的表迭代器,我们可以获得k和v的值。
在in关键字后接需要被迭代的数据源列表(也就是说可以迭代多个列表),然后在do后对遍历项进行处理。
Ps:其实在lua中,for的执行顺序是这样的:
- 首先,初始化,计算 in 后面表达式的值,表达式应该返回范性 for 需要的三个值:迭代函数,状态常量和控制变量;与多值赋值一样,如果表达式返回的结果个数不足三个会自动用 nil 补足,多出部分会被忽略。
- 第二,将状态常量和控制变量作为参数调用迭代函数(注意:对于 for 结构来说,状态常量没有用处,仅仅在初始化时获取他的值并传递给迭代函数)。
- 第三,将迭代函数返回的值赋给变量列表。
- 第四,如果返回的第一个值为 nil 循环结束,否则执行循环体。
- 第五,回到第二步再次调用迭代函数
从某种意义上来说,for循环还是依赖于while循环做的优化。
其等价为:
1 | do |
无状态迭代器
上面我们依据闭包的思想实现的迭代器其核心思想就是保留状态,那有没有一种方式无需保留状态构建迭代器呢?
让我们回想一下,系统自带的pairs(t)迭代器有使用到闭包吗?答案是:没有
所以pairs(t)迭代器就是一种无状态迭代器~
我们尝试着实现一个pairs的效果,其代码如下:
1 | function iter(a,i) |
我们每次调用ipairs时,都自动去调用iter,并且在调用时保留iter迭代函数,a迭代数据,0迭代索引。(很神奇吧,这种写法估计只有lua的作者才能想到,简直天才~)
Ps:同理,lua中ipairs也是这样调用其他函数的(调用next函数)
多状态控制器
很多情况下,迭代器需要保存多个状态信息而不是简单的状态常量和控制变量,最
简单的方法是使用闭包,还有一种方法就是将所有的状态信息封装到 table 内,将 table
作为迭代器的状态常量,因为这种情况下可以将所有的信息存放在 table 内,所以迭代函
数通常不需要第二个参数。
[toc]



