chapter9_3 协同程序实现迭代器
将循环迭代器视为"生产者-消费者"模式的一种特例:迭代器产生的数据供循环体消费。
因此,用协同程序写迭代器就理所当然了。因为协同程序可以一改传统调用者与被调用者之间的关系。
有了这个特性,在写迭代器时就无须顾及如何在每次成功的迭代调用间保持状态了。
function permgen(a,n)
n = n or #a --默认的n是数组a的大小
if n <= then --只有一个元素,不需要排列
printresult(a)
else
for i = ,n do
a[n],a[i] = a[i],a[n] --把第i个元素放在最末尾
permgen(a,n-) --用余下的元素产生排列
a[n],a[i] = a[i],a[n] --恢复第i个元素
end
end
end
permgen调用如下:
function printResult(a)
for i=,#a do
io.write(a[i]," ")
end
io.write("\n")
end permgen({,,,})
--> 2 3 4 1
--> 3 2 4 1
......
-->1 2 3 4
有了迭代器的generator函数,将它转换为一个迭代器就容易多了.
首先将printResult改为yield:
function permgen(a,n)
n = n or #a
if n <= then
coroutine.yield(a)
else
for i = ,n do
a[n],a[i] = a[i],a[n] --把第i个元素放在最末尾
permgen(a,n-) --用余下的元素产生排列
a[n],a[i] = a[i],a[n] --恢复第i个元素
end
end
end
然后定义一个工厂函数,用于将generator函数放到一个协同程序中运行,并创建迭代器函数。
迭代器只是简单地唤醒协同程序,让其产生下一种排列:
function permutations(a) --迭代器工厂函数
local co = coroutine.create(function () permgen(a) end) --生成函数在协同程序中运行
return function() --迭代器函数
local code , res = coroutine.resume(co) --只是简单地唤醒协同程序
return res
end
end
有了上面的函数,在for语句中遍历一个数组的所有排列就非常简单了:
for p in permutations{"a","b","c"} do
printResult(p)
end -->b c a
-->c b a
-->c a b
-->a c b
-->b a c
-->a b c
permutations函数使用了一种Lua中比较常见的模式,就是将一条唤醒协同程序的调用包装在一个函数中。
由于这种模式比较常见,Lua专门提供了一个函数coroutine.wrap来完成这个功能。
类似于create,wrap创建了一个新的协同程序。但不同的是,wrap并不是返回协同程序本身,而是一个函数。
每当调用这个函数,即可唤醒一次协同程序。但这个函数与resume的不同之处在于,它不会返回错误代码。
当遇到错误时,它会引发错误。若使用wrap,可以这样写:
function permutations(a) --协同程序迭代器升级版
return coroutine.wrap(function () permgen(a) end)
end
wrap要比coroutine.create更容易使用。它提供了一个对于协同程序编程实际所需的功能:即一个可以唤醒协同程序的函数。
但是缺乏灵活性,无法检查wrap所创建的协同程序的状态,此外,也无法检测出运行时的错误。
和resume返回值相同,只是没有第一个布尔量。如果发生任何错误,抛出这个错误。
chapter9_3 协同程序实现迭代器的更多相关文章
- 《Lua程序设计》9.3 以协同程序实现迭代器 学习笔记
例:编写一个迭代器,使其可以遍历某个数组的所有排列组合形式.代码如下: function permgen(a, n) n = n or #a -- 默认n为a的大小 then -- 还需要改变吗? p ...
- Lua 学习笔记(九)协同程序(线程thread)
协同程序与线程thread差不多,也就是一条执行序列,拥有自己独立的栈.局部变量和命令指针,同时又与其他协同程序共享全局变量和其他大部分东西.从概念上讲线程与协同程序的主要区别在于,一个具有多个线程的 ...
- 【转】Unity中的协同程序-使用Promise进行封装(二)
原文:http://gad.qq.com/program/translateview/7170970 译者:王磊(未来的未来) 审校:崔国军(飞扬971) 在上一篇文章中,我们的注意力主要是 ...
- 【转】Unity中的协同程序-使用Promise进行封装(一)
原文:http://gad.qq.com/program/translateview/7170767 译者:陈敬凤(nunu) 审校:王磊(未来的未来) 每个Unity的开发者应该都对协同程序非 ...
- Unity 中的协同程序
今天咱就说说,协同程序coroutine.(这文章是在网吧敲的,没有unity,但是所有结论都被跑过,不管你信得过我还是信不过我,都要自己跑一下看看,同时欢迎纠错)先说说啥是协程:协同程序是一个非常让 ...
- Lua学习笔记4. coroutine协同程序和文件I/O、错误处理
Lua学习笔记4. coroutine协同程序和文件I/O.错误处理 coroutine Lua 的协同程序coroutine和线程比较类似,有独立的堆栈.局部变量.独立的指针指令,同时又能共享全局变 ...
- Lua 学习之基础篇九<Lua 协同程序(Coroutine)>
引言 讲到协程,首先来介绍一下线程和协程的区别 lua协程和多线程 相同之处:拥有自己独立的桟.局部变量和PC计数器,同时又与其他协程共享全局变量和其他大部分东西 不同之处:一个多线程程序可以同时运行 ...
- Unity3D协同程序(Coroutine)
摘要下: 1. coroutine, 中文翻译"协程".这个概念可能有点冷门,不过百度之,说是一种很古老的编程模型了,以前的操作系统里进程调度里用到过,现在操作系统的进程调度都是根 ...
- 【转】Unity中的协同程序-使用Promise进行封装(三)
原文:http://gad.qq.com/program/translateview/7170967 译者:崔国军(飞扬971) 审校:王磊(未来的未来) 在这个系列的最后一部分文章,我们要通过 ...
随机推荐
- 【故障】当Eclipse打不开的时候
某天,当你打开Eclipse的时候,弹出这种路径错误的界面.那么,该怎么办呢??? 参考: https://zhidao.baidu.com/question/1497777962705951219. ...
- 职责链模式(Chain of Responsibility)(对象行为型)
1.概述 你去政府部门求人办事过吗?有时候你会遇到过官员踢球推责,你的问题在我这里能解决就解决,不能解决就推卸给另外个一个部门(对象).至于到底谁来解决这个问题呢?政府部门就是为了可以避免屁民的请求与 ...
- 区块链Fabric技术在托管业务中的运用初探
区块链Fabric技术在托管业务中的运用初探 什么是Fabric技术 HyperLedger是IBM.Intel等多家公司正开展的一个区块链项目,包含了Fabric.Iroha等多项技术,其中最为活跃 ...
- Android Studio新手
目标:Android Studio新手–>下载安装配置–>零基础入门–>基本使用–>调试技能–>构建项目基础–>使用AS应对常规应用开发 AS简介 经过2年时间的研 ...
- Python学习笔记——基础篇【第四周】——迭代器&生成器、装饰器、递归、算法、正则表达式
目录 1.迭代器&生成器 2.装饰器 a.基本装饰器 b.多参数装饰器 3.递归 4.算法基础:二分查找.二维数组转换 5.正则表达式 6.常用模块学习 #作业:计算器开发 a.实现加减成熟及 ...
- juit测试中报错:org.hibernate.HibernateException: Unable to get the default Bean Validation factory
org.hibernate.HibernateException: Unable to get the default Bean Validation factory 解决方法: 解决方案: 在hib ...
- 关于oracle数据库(11)
事务 事务是最小的工作单元,是对数据库的若干操作,增删查改(要不就都成功,要不就都失败) 在oracle数据库中,事务是默认打开的,其他数据库都需要一条语句来打开事务,默认关闭的 事务的特征 原子性. ...
- wall time
"showing elapsed time and wall clock time correspondingly." what's difference between elap ...
- JAVA中方法的定义与使用(课堂学习归纳)
组合数,百度词条是这样解释的:从m个不同元素中取出n(n≤m)个元素的所有组合的个数,叫做从m个不同元素中取出n个元素的组合数(Combination) 对于计算组合数,需要一定的工作量,计算机可以很 ...
- 批量安装XP补丁的命令
方法一: 新建一个bat文件,把这个文件和所有补丁文件放在同一个目录下,双击运行. BAT代码如下 @echo offfor %%i in (*.exe) do %%i /passive /nores ...