1.迭代器与closure的关系
所谓迭代器,就是对一个集合的遍历,比如遍历一个table数组,我们必须在每遍历完一个元素之后,我们必须记住下一个元素的索引。
前几节我们学过了闭合函数,它存在的非局部的变量,就是能够在多次调用闭合函数(返回的函数+非局部的变量)后,保留非局部变量的值,利用这一点,我们可以很容易的自定义一个迭代器
比如遍历一个t = {12,23,15,19}数组,自定义迭代器如下
function values(t)
local i = 0;
return function() i = i+1 return t[i] end;
end
遍历方式有两种while xxx do ... end 或者用本节讲的for来遍历,
t = {12,23,15,19};
前者方面
iter = values(t);
while true do
local elem = iter();
if nil == elem then break end;
print(elem);
end
后者方法,采用for
for elem in values(t) do
print(elem);
end
两种方法,显然for比较简洁一些,for会多次调用<expr-list>(泛型for格式:for <val-list> in <expr-list> do ... end)所处的迭代器(称为迭代工厂也行)
下面举一个更为复杂的迭代器,遍历 输入文件当中的单词,必须用两个变量来记住当前读到的文字所处行line,以及当前的列的位置pos
首先创建一个迭代器
function allwords()
local line = io.read(); --读取一行文本
local pos = 1;--初始当前为第一列的位置
return function()
while line do -- 至少有一行文本
local s,e = stirng.find(line,"%w+",pos) --调用string.find方法,第一个参数为当前文本串,第二个参数为正则表达式,表示单词,第三个参数表示,从line的第pos列开始查找
if s then -- 找到了单词的情况
pos = e+1; -- 移动pos的索引位置
return string.sub(line,s,e); --节取line从s到e索引对应的单词,并返回
else
line = io.read() --如果上一行文本内已经找不到单词了,再读取一行
pos = 1--重新将pos置到第一列
end
end
return nil --没有文本,返回空
end
end
我们用for可以简化代码,实现遍历如下:
for word in allwords() do
print(word)
end
2 强大的泛型for
我们应该正确理解LUA提供的FOR泛型的强大之处,
我们知道,泛型for格式:for <val-list> in <expr-list> do ... end,正常情况下<val-list>这个变量列表可以是一个或多个,一般是三个,而<expr-list>也可以是一个或多个表达式,但一般情况是一个.
上面所举的两个例子(遍历数组,遍历文件当中的单词,我们称之无状态的迭代器,为什么?)有时候,我们不想迭代器本身保留着一些状态,或者控制变量,而希望迭代器本身不存在什么状态,而是将诸如控制变量,恒定状态等信息从迭代器中分离出来,这时候,我们就需要泛型for了。
泛型for支持每次调用迭代工厂后,返回迭代器的一些状态给<val-list>,即for ... in ... do ... end在处理时,首先处理in后面的表达式,一般处理后返回三个值,分别是:迭代函数(工厂)func,恒定状态 list,控制变量 index 这三个值,之后,利用返回的后两个值(list,index作为func函数的参数,调用func,返回给in之前的变量列表<var-list>)
举例:(无状态迭代器,状态交给了泛型for)还是以遍历数组为例(下面的代码其实是LUA ipairs方法的实现原理)
t = {12,23,15,19}
function values(t,i)
i = i+1;
return function() return i , t[i] end;
end
function iter(t)
return values,t,0
end
定义了上面的iter迭代器之后,我们可以这样子遍历数组了
for i,v in iter(t) do
print(i,v);
end
3较为复杂的有状态迭代器
我们将本节1当中举的例子(代码如下)有状态迭代器,修改成较复杂的有状态迭器
修改前:
function allwords()
local line = io.read(); --读取一行文本
local pos = 1;--初始当前为第一列的位置
return function()
while line do -- 至少有一行文本
local s,e = stirng.find(line,"%w+",pos) --调用string.find方法,第一个参数为当前文本串,第二个参数为正则表达式,表示单词,第三个参数表示,从line的第pos列开始查找
if s then -- 找到了单词的情况
pos = e+1; -- 移动pos的索引位置
return string.sub(line,s,e); --节取line从s到e索引对应的单词,并返回
else
line = io.read() --如果上一行文本内已经找不到单词了,再读取一行
pos = 1--重新将pos置到第一列
end
end
return nil --没有文本,返回空
end
end
修改后:
function allwords()
local state = {line = io.read(),pos = 1} --将(读取一行文本--初始当前为第一列的位置)的数据放到一个table里边,名为state
return myIterator,state
end
function myIterator(state)
while state.line do -- 至少有一行文本
local s,e = stirng.find(state.line,"%w+",state.pos) --调用string.find方法,第一个参数为当前文本串,第二个参数为正则表达式,表示单词,第三个参数表示,从line的第pos列开始查找
if s then -- 找到了单词的情况
state.pos = e+1; -- 移动pos的索引位置
return string.sub(state.line,s,e); --节取line从s到e索引对应的单词,并返回
else
state.line = io.read() --如果上一行文本内已经找不到单词了,再读取一行
state.pos = 1--重新将pos置到第一列
end
end
return nil --没有文本,返回空
end
修改后的遍历跟修改前一样
for word in allwords() do
print(word)
end
-------------------迭代器就讲到这里,下一节将讲解-(6)LUA程序设计-编译执行与错误(compile 、run & error)处理------------
LUA技术交流群,请加Q群:139315537,加入请注明来源。
分享到:
相关推荐
而lua-resty-template和大多数模板引擎是类似的,大体内容有: 模板位置:从哪里查找模板; 变量输出/转义:变量值输出; 代码片段:执行代码片段,完成如if/else、for等复杂逻辑,调用对象函数/方法; 注释:解释...
lua-nginx-module-0.10.13
安装nginx_lua模块时候需要先安装nginx的依赖包,安装命令rpm -ivh lua-devel-5.1.4-4.1.el6.x86_64.rpm
EmmyLua-AttachDebugger-1.0.0.4 最新intellij 断点调试
lua-resty-core, 新的基于 lua Nginx 模块的API 电子邮件名称lua-resty-core - 用于ngx_http_lua_module和/或者ngx_stream_lua_module的基于new的Lua table-内容名称状态概要说明描述先决条件API实现了r
lua-nginx-module-master,nginx编译lua模块必需文件lua-nginx-module
nginx集成lua脚本模块,配合nginx和ngx_devel_kit一起使用,注意lua_nginx_module的版本号,否则会出现时间类型不兼容
lua-resty-redis-connector-master lua-resty的redis库 lua-resty的redis库
Lua程序设计 5.1中文手册 5.1源码 Lua程序设计 5.1中文手册 5.1源码 Lua程序设计 5.1中文手册 5.1源码
lua中的json模块,用于解析json字符串
LUA程序设计教程LUA程序设计教程LUA程序设计教程LUA程序设计教程LUA程序设计教程LUA程序设计教程LUA程序设计教程LUA程序设计教程LUA程序设计教程LUA程序设计教程LUA程序设计教程LUA程序设计教程LUA程序设计教程
LUA-cjson已经编译 LUA-cjson已经编译 LUA-cjson已经编译 LUA-cjson已经编译 LUA-cjson已经编译 LUA-cjson已经编译
nginx安装lua、jwt模块,通过lua验证jwt实现蓝绿发布样例demo,配置直接可用 luajit2-2.1-20220411.tar.gz #luajit官网存在一定的坑,下载openresty的优化版本 lua-nginx-module-0.10.22.tar.gz # 0.10.16 以后都...
OpenResty 是一个强大的 Web 应用服务器,Web 开发人员可以使用 Lua 脚本语言调动 Nginx 支持的各种 C 以及 Lua 模块,更主要的是在性能方面,OpenResty可以 快速构造出足以胜任 10K 以上并发连接响应的超高性能 Web ...
安装lua-language-server 可以用于nvim中lua代码自动补全 使用方法可参考文章: https://blog.csdn.net/lxyoucan/article/details/120292520
lua-upstream-nginx-module, Nginx C 模块将Lua向ngx_lua公开,用于 Nginx upstreams 电子邮件名称ngx_http_lua_upstream - Nginx MODULE,用于向 Nginx upstreams公开Lua到 ngx_lua目录NAME状态概要说明函数get_...
lua-resty-validation, 用于Lua和OpenResty的验证库( 输入验证和筛选) lua-resty-validationlua-resty-validation 是用于Lua和OpenResty的可以扩展链接验证和过滤库。带lua-resty-validation的 Hello Worldlocal val
lua-resty-memcached服务器 那是一个基于openresty的memcached服务器(带有nginx-tcp-lua-server补丁)。 它现在仅支持设置/获取操作。 使用exmaple(内存缓存协议) 句法: --> set key1 0 0 3 --> val &...
Binary Package lua-devel-5.1.4-4.1.el6.x86_64.rpm Source Package lua-5.1.4-4.1.el6.src.rpm Install HowtoInstall the lua-devel rpm package: ..
离线安装包,亲测可用