Lua中的迭代器与泛型for
【前言】
迭代器就是一种可以遍历一种集合中所有元素的机制,在Lua中,通常将迭代器表示为函数。每调用一次函数,就返回集合中的“下一个”元素。每个迭代器都需要在每次成功调用之后保存一些状态,这样才能知道它所在的位置及如何走到下一个位置,通过之前博文的总结,闭包对于这样的任务提供了极佳的支持。现在我们就用代码来实现一个简单的迭代器。
function values(tb)
local i =
return function ()
i = i +
return tb[i]
end
end local testTb = {, , }
for value in values(testTb) do
print(value)
end
这就是一个最简单的迭代器,使用闭包来完成整个任务;这只是一个简单的例子,接下来,再看看泛型for的语义。
【泛型for的语义】
泛型for比较复杂,它在循环过程内保存了迭代器函数。它实际上保存着3个值:一个迭代器函数、一个恒定状态和一个控制变量。接下来,分别进行总结。
泛型for的语法如下:
for <var-list> in <exp-list> do
<body>
end
其中,<var-list>是一个或多个变量名的列表,以逗号分隔;<exp-list>是一个或多个表达式的列表,同样以逗号分隔。通常表达式列表只有一个元素,即一句对迭代器函数的调用。例如:
for k, v in pairs(t) do print(k, v) end
for做的第一件事就是对in后面的表达式求值,这些表达式应该返回3个值供for保存:迭代器函数、恒定状态和控制变量的初值。这里和多重赋值是一样的,只有最后一个表达式才会产生多个结果,并且只会保留前3个值,多余的值会被丢弃;而不够的话,就以nil补足。
在初始化完成以后,for会以恒定状态和控制变量来调用迭代器函数。然后for将迭代器函数的返回值赋予变量列表中的变量。如果第一个返回值为nil,那么循环就终止,否则,for执行它的循环体,随后再次调用迭代器函数,并重复这个过程。在前言部分的代码中,只是返回了迭代器函数,并没有返回恒定状态和控制变量。下面通过代码来说明这个问题,比如:
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
end
【无状态的迭代器】
所谓“无状态的迭代器”,就是一种自身不保存任何状态的迭代器。因此,我们可以在多个循环中使用同一个无状态的迭代器,避免创建新的闭包的开销。
在每次迭代中,for循环都会用恒定状态和控制变量来调用迭代器函数。一个无状态的迭代器可以根据这两个值来为下次迭代生成下一个元素。这类迭代器的代表就是ipairs。它可以用来迭代一个数组的所有元素。如下述演示代码:
local aTb = {"One", "Two", "Three"}
for i, v in ipairs(aTb) do
print(i, v)
end
在这里,迭代器状态就是需要遍历的table(一个恒定状态,它不会在循环中改变)及当前的索引值(控制变量)。我们可以使用Lua代码来实现ipairs,大概就如下代码:
local function iter(a, i)
i = i +
local v = a[i]
if v then
return i, v
end
end function ipairs(a)
return iter, a,
end
函数pairs与ipairs类似,也是用于遍历一个table中的所有元素。不同的是,它的迭代器函数是Lua中的一个基本函next。
function pairs(a)
return next, t, nil
end
在调用next(t, k)时,k是table t的一个key。此调用会以table中的任意次序返回一组值:此table的下一个key,及这个key所对应的值。而调用next(t, nil)时,返回table的第一组值。若没有下一组值时,next返回nil。所以,我们也可以使用next来判断一个table是否为空。
对于大家经常迷惑的ipairs和pairs的区别,在这里就能看的一清二楚了,ipairs只能用于遍历index是整型的table,同时,由于ipairs返回的控制变量初值为0,这就决定了,ipairs只能访问index从1开始的key和value;ipairs不能返回nil,当key对应的值为nil时,就直接终止遍历;而pairs则没有要求。关于ipairs和pairs的具体差异,请参考这篇博文:点这里。
当然了,有了无状态的迭代器,就有了有状态的迭代器了,有状态的迭代器就是专门用一个table来保存状态;在无状态的迭代器中,我们每一次都是迭代一个table,这个table就是一个无状态的table,它不会再遍历的过程中发生变化,而有状态的迭代器,则会在遍历的过程中对迭代的table进行变更,迭代的table的状态也随之发生了变化。这里不做详细的总结。
Lua中的迭代器与泛型for的更多相关文章
- Lua学习(5)——迭代器与泛型for
1. 迭代器 2. 泛型for语义 所谓迭代器就是一种可以遍历一种集合中所有元素的机制.在lua中,迭代器通常表示为函数,每调用依次函数就返回集合中的下一个元素.泛型for 内部保存了迭代器函数 实际 ...
- Lua迭代器和泛型for
1.迭代器与closure 在lua中,迭代器通常为函数,每调用一次函数,会返回集合中的下一个元素.每个迭代器在成功调用的时候,都需要保存一些状态,closure(闭包)完美为迭代器运用而生. fun ...
- lua迭代器和泛型for浅析
(一) 首要概念要理清: 1. 在lua中,函数是一种"第一类值",他们具有特定的词法域."第一类值"表示在lua中函数与其他传统类型的值(例如数字和字符串)具 ...
- Step By Step(Lua迭代器和泛型for)
Step By Step(Lua迭代器和泛型for) 1. 迭代器与Closure: 在Lua中,迭代器通常为函数,每调用一次函数,即返回集合中的"下一个"元素.每个迭代器都 ...
- Lua语法基础(3)--迭代器和泛型for
迭代器和闭包 迭代器是一种支持指针类型的结构,它可以遍历集合的每一个元素.在Lua中我们常常使用函数来描述迭代器,每次调用该函数就返回集合的下一个元素. 迭代器需要保留上一次成功调用的状态和下一次成功 ...
- Lua中的语句
[赋值] 赋值的基本含义是修改一个变量或一个table中字段的值,这个和其它语言没有多少区别,但是对于Lua,有一个特性,它允许“多重赋值”,也就是一下子将多个值赋予多个变量,例如以下代码: , pr ...
- Lua中的控制结构
Lua提供了一组传统的.小巧的控制结构,包括用于条件执行的if,用于迭代的while.repeat和for.所有的控制结构都有意个显式的终止符:if.for和while以end作为结尾,repeat以 ...
- 两个函数彻底理解Lua中的闭包
本文通过两个函数彻底搞懂Lua中的闭包,相信看完这两个函数,应该能理解什么是Lua闭包.废话不多说,上 code: --[[************************************** ...
- lua中遍历table的几种方式比较
当我在工作中使用lua进行开发时,发现在lua中有4种方式遍历一个table,当然,从本质上来说其实都一样,只是形式不同,这四种方式分别是: for key, value in pairs(tbtes ...
随机推荐
- 使用jprofiler分析dump文件一个实例
3 .dump 线上文件栈 [root@yszyz10a153 ~]# jmap -dump:live,format=b,file=heap201712.hropf 72947 参考:https:/ ...
- 极光推送JAVA代码示例
一. 准备工作 1. 登录极光推送官网https://www.jpush.cn/,注册账号并登录 2. 创建应用 创建应用过程,详见百度经验:http://jingyan.baidu.com/arti ...
- UOJ129 NOI2015 寿司晚宴 数论、状压DP
传送门 数论题\(n \leq 500\)肯定是什么暴力算法-- 注意到每一个数\(> \sqrt{n}\)的因子最多只有一个,这意味着\(> \sqrt{n}\)的因子之间是独立的,而只 ...
- 全解史上最快的JOSN解析库 - alibaba Fastjson
JSON,全称:JavaScript Object Notation,作为一个常见的轻量级的数据交换格式,应该在一个程序员的开发生涯中是常接触的.简洁和清晰的层次结构使得 JSON 成为理想的数据交换 ...
- 相约南湖,南京都昌信息亮相南湖HIT论坛
金秋十月,雨过南湖水似油 ,烟雾蒙蒙净长空 2017年10月15日, 南湖HIT论坛迎来了第六届.本次论坛吸引了500名来自全国各地医疗机构.卫生行政主管部门的信息化主管和医疗IT企业的精英,齐聚嘉兴 ...
- cookie跨域共享
domain和path属性,domain就是当前域,默认为请求的地址,如网址为www.jb51.net/test/test.aspx,那么domain默认为www.jb51.net,path默认就是当 ...
- (PAT)L2-004 这是二叉搜索树吗?(数据结构)
题目链接:https://www.patest.cn/contests/gplt/L2-004 一棵二叉搜索树可被递归地定义为具有下列性质的二叉树:对于任一结点, 其左子树中所有结点的键值小于该结点的 ...
- SELECT list is not in GROUP BY clause and contains nonaggregated column
报错如下: Expression # of SELECT list is not in GROUP BY clause and contains nonaggregated column ‘sss.m ...
- springdata jpa 原始sql的使用
- 清明培训 清北学堂 DAY2
今天是钟皓曦老师的讲授~~ 总结了一下今天的内容: 数论!!! 1.整除性 2.质数 定义: 性质: 3.整数分解定理——算数基本定理 证明: 存在性: 设N是最小不满足唯一分解定理的整数 (1) ...