所谓“迭代器”就是一种可以遍历(iterate over)一种极和中所有元素的机制。在Lua中,通常将迭代其表示为函数。每调用一次函数,即返回集合中的“下一个”元素。
每个迭代器都需要在每次成功调用之间保持一种状态,这样才能知道它所在的位置及如何步进到下一个位置。closure对于这类人无提供了极佳的支持,一个closure就是一种可以访问外部嵌套环境中的局部变量的函数。对于closure而言,这些变量就可用于在成功调用之间保持状态值,从而使closure可以记住它在一次遍历中所在的位置。当然,为了创建一个新的closure,还必须创建它的这些“非局部的变量(non-local variable)”。因此一个closure结构通常涉及到两个函数:closure本身和一个用于创建该closure的工厂(factory)函数。
作为示例,来为列表写一个简单的迭代器。与ipairs不同的是该迭代式并不是返回每个元素的索引,而是返回元素的值(返回什么还不是由自己决定嘛):

function values (t)
local i =
return function () i = i + ; return t[i] end
end

在本例中,values就是一个工厂。每当调用这个工厂时,它就创建一个新的closure(即迭代器本身)。这个closure将它的状态保存在其外部变量t和i中。每当调用这个迭代器时,它就从列表t中返回下一个值。知道最后一个元素返回后,迭代其就会返回nil,一次表示迭代的结束。
可以在一个while循环中使用这个迭代器:

t = {, , }
iter = values(t) -- 创建迭代器
while true do
local element = iter() -- 调用迭代器
if element == nil then break end
print(element)
end

然而使用泛型for则更为简单。接下来会发现,它真实为这种迭代而设计的:

t2 = {, , }
for element in values(t2) do
print(element)
end

泛型for为一次迭代循环做了所有的蒲记工作。它在内部保存了迭代器函数,因此不再需要iter变量。它在每次新迭代时调用迭代器,并在迭代器返回nil时结束循环。

[迭代器示例——遍历文件中所有单词]
下面的示例中展示了一个可以遍历当前输入文件中所有单词的迭代器——allwords。为了完成这样的遍历,需要保持两个值:当前行的内容(变量line)及在该行中所处的位置(变量pos)。
这里用到一个string.find函数,返回当前查找单词位置。
尽管迭代器本身具有复杂性,但allwords的使用还是很简明易懂的:

for word in allwords() do
print(word)
end

对于迭代器而言,一种常见的情况就是:编写迭代器本身或许不太容易,但使用它们却是很容易的。这也不会称为一个大问题,因为通常使用Lua编成的最终用户不会去定义迭代器,而只是使用那些程序提供的迭代器。

function allwords ()
local line = io.read() -- 当前行
local pos = -- 一行中的当前位置
return function() -- 迭代器函数
while line do -- 若为有效的行内容就进入循环
local s, e = string.find(line, "%w+", pos)
if s then -- 是否找到一个单词
pos = e + -- 该单词的下一个位置
return string.sub(line, s, e) -- 返回该单词
else
line = io.read() -- 没有找到单词,返回下一行
pos = -- 在第一个位置重新开始
end
end
return nil -- 没有其余行了,遍历结束
end
end

Lua 迭代器与closure的更多相关文章

  1. Lua迭代器和泛型for

    1.迭代器与closure 在lua中,迭代器通常为函数,每调用一次函数,会返回集合中的下一个元素.每个迭代器在成功调用的时候,都需要保存一些状态,closure(闭包)完美为迭代器运用而生. fun ...

  2. Lua 迭代器

    第一种:lua迭代器的实现依赖于闭包(closure)特性 1.1 第一个简单的写法 --迭代器写法 function self_iter( t ) local i = 0 return functi ...

  3. lua迭代器和泛型for浅析

    (一) 首要概念要理清: 1. 在lua中,函数是一种"第一类值",他们具有特定的词法域."第一类值"表示在lua中函数与其他传统类型的值(例如数字和字符串)具 ...

  4. Step By Step(Lua迭代器和泛型for)

    Step By Step(Lua迭代器和泛型for) 1. 迭代器与Closure:    在Lua中,迭代器通常为函数,每调用一次函数,即返回集合中的"下一个"元素.每个迭代器都 ...

  5. Lua中的closure(闭合函数)

    词法域:若将一个函数写在另一个函数之内,那么这个位于内部的函数便可以访问外部函数中的局部变量,这项特征称之为“词法域”. 例:假设有一个学生姓名的列表和一个对应于没个姓名的年级列表,需要根据每个学生的 ...

  6. Lua学习十一----------Lua迭代器

    © 版权声明:本文为博主原创文章,转载请注明出处 Lua迭代器 - 迭代器(iterator)是一种对象,它能够用来遍历标准模板库容器中的部分或全部元素,每个迭代器对象代表容器中的确定的地址 - Lu ...

  7. [Lua] 迭代器 闭合函数 与 泛型for

    首先看看一下闭合函数(closure),见如下代码: function newCounter() local i = 0 -- 非局部变量(non-local variable) return fun ...

  8. lua迭代器和仿制药for

    不管是什么样的结构,你只需要同意遍历集合可以称为迭代器的所有元素.lua常用来形容叙事功能迭代器.个元素.每个迭代器都须要保存一些状态来知道当前处于什么位置和怎样进行下一次迭代. 对于这种任务.闭包提 ...

  9. Lua迭代器

    在Lua中我们常常使用函数来描述迭代器,每次调用该函数就返回集合的下一个元素.迭代器需要保留上一次成功调用的状态和下一次成功调用的状态,可以通过闭包提供的机制来实现这个任务(闭包中的外部局部变量可以用 ...

随机推荐

  1. Java如何比较两个数组?

    在Java中,如何比较两个数组? 示例 以下示例使用equals方法来检查两个数组是否相等. package com.yiibai; import java.util.*; public class ...

  2. Java如何从数组中查找公共的元素?

    在Java中,如何从数组中查找公共的元素? 示例 以下示例显示了如何从两个数组中查找公共元素并将其存储在数组中. package com.yiibai; import java.util.*; pub ...

  3. mysql存储过程----临时表 temporary

    在存储过程中可以使用临时表,下面有一个分割字符串的例子 语法 1.创建:create temporary table 表名(列信息); 2.删除:drop table 表名; 3.清空:truncat ...

  4. 使用VS2017新建的Web项目报错:Package Microsoft.Composition 1.0.27 is not compatible with netcoreapp1.1

    使用VS2017新建的Web项目报错: 看到这样的错误提示,毫无意义.赶脚这应该是VS2017的BUG,没有显示错误的位置.于是用dotnet restore手动还原,结果在控制台中终于显示了详细的错 ...

  5. 有空研究一下 superwebsocket (底层是 supersocket) 用来实现 web聊天什么的

    参考:http://superwebsocket.codeplex.com/ 一个老外写的 asp.net 下socket的多钟方案推荐 :http://www.codeproject.com/Art ...

  6. java 项目 存入mysql后 变问号 MySql 5.6 (X64) 解压版 1067错误与编码问题的解决方案

    [参考]MySQL 5.7.19 忘记密码 重置密码 my.ini示例 服务启动后停止 环境 Java环境JDK1.8  安装好了 mysql-5.6.38-winx64  idea2016(64) ...

  7. lakala proportion轨迹分析代码

    /** * Created by lkl on 2017/12/7. */ import breeze.numerics.abs import org.apache.spark.sql.SQLCont ...

  8. jsTree 插件

    html代码 <div id="jstree1"></div> js代码: <script src="__STATIC__/h5/js/jq ...

  9. UNIX环境编程学习笔记(4)——文件I/O之dup复制文件描述符

    lienhua342014-08-23 UNIX 提供了两个函数 dup 和 dup2 用于复制一个现存的文件描述符. #include <unistd.h> int dup(int fi ...

  10. Mac OS X 下安装MySQL 5.7

    下载安装包 官网下载安装包 选择相应的版本和格式,有 .dmg 和压缩包两种. 这里选择简单直接的 .dmg安装包,下载的时候可以将下载地址直接贴到迅雷,速度比较快. 安装 安装很简单,直接双击下好的 ...