您的位置:首页 > 编程语言 > Lua

lua的coroutine 协同程序实现迭代器

2017-02-21 00:00 561 查看
reference:
http://blog.csdn.net/wzzfeitian/article/details/8832017
下面我们就看一下coroutine为我们提供的强大的功能,用coroutine来实现迭代器。
我们来遍历一个数组的全排列。先看一下普通的loop实现,代码如下:
function printResult(a)
for i = 1, #a do
io.write(a[i], ' ')
end
io.write('\n')
end

function permgen(a, n)
n = n or #a
if n <= 1 then
print("write value")
printResult(a)
else
for i = 1, n do

print("start: ", i,n,a[i],a
)
a
, a[i] = a[i], a

print(a[i],a
)
permgen(a, n-1)
a
, a[i] = a[i], a

print("n: ", n, a[i],a
)
end
end
end

permgen({"a","b","c"})

执行结果:

start: 	1	3	a	c
c	a
start: 	1	2	c	b
b	c
write value
b c a
n: 	2	c	b
start: 	2	2	b	b
b	b
write value
c b a
n: 	2	b	b
n: 	3	a	c
start: 	2	3	b	c
c	b
start: 	1	2	a	c
c	a
write value
c a b
n: 	2	a	c
start: 	2	2	c	c
c	c
write value
a c b
n: 	2	c	c
n: 	3	b	c
start: 	3	3	c	c
c	c
start: 	1	2	a	b
b	a
write value
b a c
n: 	2	a	b
start: 	2	2	b	b
b	b
write value
a b c
n: 	2	b	b
n: 	3	c	c

再看一下迭代器实现,注意比较下代码的改变的部分:

function printResult(a)
for i = 1, #a do
io.write(a[i], ' ')
end
io.write('\n')
end

function permgen(a, n)
n = n or #a
if n <= 1 then
coroutine.yield(a)
else
for i = 1, n do
a
, a[i] = a[i], a

permgen(a, n-1)
a
, a[i] = a[i], a

end
end
end

function permutations(a)
local co = coroutine.create(function () permgen(a) end)
return function ()
local code, res = coroutine.resume(co)
return res
end
end

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中的常规模式,将在函数中去resume一个对应的coroutine进行封装。Lua对这种模式提供了一个函数coroutine.wap 。跟create 一样,wrap 创建一个新的coroutine ,但是并不返回给coroutine,而是返回一个函数,调用这个函数,对应的coroutine就被唤醒去运行。跟原来的resume 不同的是,该函数不会返回errcode作为第一个返回值,一旦有error发生,就退出了(类似C语言的assert)。使用wrap, permutations可以如下实现:

function printResult(a)
for i = 1, #a do
io.write(a[i], ' ')
end
io.write('\n')
end

function permgen(a, n)
n = n or #a
if n <= 1 then
coroutine.yield(a)
else
for i = 1, n do
a
, a[i] = a[i], a

permgen(a, n-1)
a
, a[i] = a[i], a

end
end
end

function permutations (a)
return coroutine.wrap(function () permgen(a) end)
end

for p in permutations({"a", "b", "c"}) do
printResult(p)
end

wrap 比create 跟简单,它实在的返回了我们最需要的东西:一个可以唤醒对应coroutine的函数。 但是不够灵活。没有办法去检查wrap 创建的coroutine的status, 也不能检查runtime-error(没有返回errcode,而是直接assert)。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  Lua