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

reference:数组

http://blog.csdn.net/wzzfeitian/article/details/8832017函数

下面咱们就看一下coroutine为咱们提供的强大的功能,用coroutine来实现迭代器。oop

咱们来遍历一个数组的全排列。先看一下普通的loop实现,代码以下:lua

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[n])
            a[n], a[i] = a[i], a[n]  
            print(a[i],a[n])
            permgen(a, n-1)  
            a[n], a[i] = a[i], a[n]  
            print("n: ", n, a[i],a[n])
        end   
    end   
end  
   
permgen({"a","b","c"})

执行结果:spa

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

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

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[n], a[i] = a[i], a[n]  
            permgen(a, n-1)  
            a[n], a[i] = a[i], a[n]  
        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

运行结果:code

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能够以下实现:blog

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[n], a[i] = a[i], a[n]  
            permgen(a, n-1)  
            a[n], a[i] = a[i], a[n]  
        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)。get