Lua 基础之迭代器
来源:互联网 发布:xmind mac 序列号 编辑:程序博客网 时间:2024/06/01 12:08
迭代器与 closure
- 迭代器是一种可以遍历集合中所有元素的机制,lua 中迭代器使用函数表示,每调用函数一次,返回集合中的下一个元素
- 迭代器除了定义一个函数之外,还必须知道元素的集合和当前的位置,因此还需要两个外部变量,这点和闭包一样,因此迭代器可以看成是使用闭包实现的
function value(t) local i = 0 return function() i = i + 1 return t[i] endendt = {1, 2, 3, 4, 5}-- 创建一个迭代器iter = value(t)-- 遍历迭代器while true do local ele = iter() if ele == nil then break end print(ele)end
- value 是一个工厂,负责生产闭包,这个闭包包括一个匿名函数和外部变量 i 和 t。调用 value 函数之后会生成一个闭包,这个闭包就是我们要的迭代器
- 使用迭代器的方式也很简单,直接调用迭代器就相当于调用闭包函数,迭代器会返回元素集合的下一个元素,当返回 nil 时就代表元素遍历完了
无状态迭代器
- 迭代器的使用方法是定义一个工厂,然后利用这个工厂生产闭包,然后调用这个闭包来获取集合中的元素。这种方式的缺点就是每次都得创建一个新的闭包,有一定的开销
- 泛型 for 循环的设计本身就包含迭代器,而且是一种无状态的迭代器,即不需要创建闭包
- 泛型 for 循环内部保存了迭代器状态,包括迭代器函数、控制变量和恒定状态
- 迭代器函数:迭代器工厂产生的匿名函数,不是闭包
- 控制变量:for 循环使用这个变量控制当前遍历的位置及何时结束遍历
- 恒定状态:迭代器遍历的目标,一般是指 table
下面我们来解析 ipairs 的实现,看看泛型 for 循环是怎样实现迭代器的
iter = function(t, i) i = i + 1 local v = t[i] if v then return i, v endendipairs = function(t) return iter, t, 0endfor i, v in ipairs(t) do print(i, v)end
- for 循环执行时会先调用 ipairs(t) ,会返回三个值,这三个值保存在 for 循环内部
_f, _s, _var = iter, t, 0
- 然后 for 循环根据控制变量 _var 来调用迭代器函数并保存在变量列表中
i, v = iter(t, _var)
- 然后更新控制变量 _var,判断控制变量是否合法,合法则继续调用迭代器函数,不合法则结束
- for 循环的实现的迭代器跟普通迭代器差不多,不同之处在于控制变量和恒定状态保存是保存 在闭包还是自己保存,普通迭代器需要创建闭包的额外代价
我们可以手动来实现一下泛型 for 循环的实现过程
function for_iterator_print(i, v, t) -- 获取迭代函数、恒定状态、控制变量 local f, s, var = ipairs(t) while true do -- 调用迭代函数 i, v = f(s, var) -- 更新控制变量 var = i -- 判断控制变量是否合法 if var == nil then break end print(i, v) endend
使用方式跟 for … in … do 相似
local i, vfor_iterator_print(i, v, t)
pairs 跟 ipairs 差不多,不同的是 pairs 的迭代器函数是 lua 定义的一个 next 函数。
自定义 pairs 的代码如下
local pairs = function(t) return next, t, nilendlocal for_iterator_print_pairsfor_iterator_print_pairs = function(k, v, t) local f, s, var = pairs(t) while true do k, v = f(s, var) var = k if k == nil then break end print(k, v) endendt = {x = 10, y = 20, z = 30}local k, vfor_iterator_print_pairs(k, v, t)
总结
- 泛型 for 实现的迭代器主要保存了 控制变量 恒定状态 迭代器函数 这三个变量,for 循环执行时会先计算 in 后面的表达式,表达式返回的值将赋给那三个变量,接下来的操作就是根据控制变量不断地调用迭代器函数,将得到的结果赋给 in 前面的变量列表
- 下面的代码是等价的
for k, v in next, t, nil do print(k, v)endfor k, v in pairs(t) do print(k, v)end
多状态迭代器
- 泛型 for 循环可以实现只有一个恒定状态的迭代器,如果有多个状态需要保存就不行了。如果要保存多个状态,可以有下面两种方式
- 使用闭包 colsure
- 把多个状态封装在一个 table 里面,然后使用泛型 for 循环
- 第一种方式会比第二种好点,一方面创建 colsure 的开销比创建 table 的开销要小,另一方面访问非局部变量比访问 table 字段要快
- 迭代器选择:泛型 for 循环 > colsure > 封装到 table
阅读全文
0 0
- Lua 基础之迭代器
- lua基础之迭代器
- Lua 基础之 Lua 程序
- Lua之coroutine基础
- Lua基础之语法
- Lua基础之Function
- cocos2dx之lua基础
- Lua之coroutine基础
- Lua之coroutine基础
- Lua 基础之数据类型
- Lua 基础之语句
- Lua 基础之函数
- Lua 基础之模块
- Lua基础之函数
- Lua基础之字符串
- lua基础之数组
- Lua脚本之基础语法
- Lua基础之table详解
- 值得推荐的C/C++框架和库
- 安装android studio遇上的问题
- 剑指offer——从尾至头打印链表
- HDU
- 【原创】git的相关基础知识笔记(一)
- Lua 基础之迭代器
- 第一篇 DTD介绍
- js判断是否包含字符串的代码;转换前端显示科学记数法的方法
- Monad详解
- UVA 489 刽子手的游戏
- UI开源库
- css 选择器总结
- pinpoint安装部署(一)
- POJ 3074 Sudoku 笔记