Lua学习笔记-迭代器和泛型for
2016-02-15 14:22
567 查看
使用迭代器例子:
上面使用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的结果:
注明:标准库提供了几种迭代器,包括用于迭代文件中每行的(io.lines)、 迭代 table 元素的(pairs)、迭代数组元素的(ipairs)、迭代字符串中单词的(string.gmatch)。注意各自的使用场景。
--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)。注意各自的使用场景。
相关文章推荐
- Lua string用法
- Lua string.format用法
- 快速掌握Lua 5.3 —— "Weak Tables"以及数学库
- lua三目运算符陷阱
- PropertyAnimation属性动画资源 ArgbEvaluator使用
- luabinding 中用Scrollview实现pageview的翻页效果
- lua 热更新设想~协程
- lua热更新~代码组织
- 快速掌握Lua 5.3 —— 面向对象编程
- 【Lua学习笔记】 --> 《字符串string与table的函数操作》
- 基于Lua脚本的自动化测试框架设计
- 快速掌握Lua 5.3 —— packages
- 文章标题
- lua 模块功能
- Lua笔记
- 快速掌握Lua 5.3 —— 环境
- luajit ffi 小结
- luajit ios arm64 编译bytecode
- 【Lua学习笔记】 --> 《类型与值、表达式与基本语法》
- lua实现多继承