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