`
suoyihen
  • 浏览: 1360072 次
文章分类
社区版块
存档分类
最新评论

用协程帮助你用最自然的思路编程

 
阅读更多
假如,想写一个循环,依次处理2,3,5,7,11....质数位置的table元素。处理函数是:
function kaka(index,ele)
print(index,ele)--当然,这里什么也没干
end
按照文字顺序,我们先写一个循环:
for index,ele in generate(table_x) do
kaka(table_x[index])
end
那个generate()函数的任务就是生产一个元组序列:
(2,ele2),(3,ele3),(5,ele5).......
这件事可以分两步来做,先写一个函数,yield这个序列,在写一个函数驱动这个协程。
function cofunc(table_x)
coroutine.yield(2,table_x[2])
coroutine.yield(3,table_x[3])
coroutine.yield(5,table_x[5])
...
end

驱动函数:
function generate(table_x)
return coroutine.wrap(cofunc(table_x))
end

完整的程序如下:

local co=require'coroutine'

function cofunc(table_x)
co.yield(2,table_x[2])
co.yield(3,table_x[3])
co.yield(5,table_x[5])
--...
end

function generate(table_x)
return coroutine.wrap(
--这里是重点!!!!!!wrap()要求参数是一个函数!
--如果没有这个貌似多于的function()包装下cofunc(),
--lua会报告 attempt to yield across metamethod/C-call boundary
--因为协程的yield操作是不能穿越C语言调用边界的,C语言是没有Lua的栈帧的
--在元方法的调用上也是同样的限制。
--增加一个空函数包装后,就增加了栈帧
--可以改写成版本2
function()
cofunc(table_x)
end
)
end

function generate2(table_x)--这样子是不是就清楚多了?
return coroutine.wrap(
function ()
co.yield(2,table_x[2])
co.yield(3,table_x[3])
co.yield(5,table_x[5])
--...
end
)
end


function kaka(index,ele)
print(index,ele)--当然,这里什么也没干
end

table_x={}
table_x[2]='a'
table_x[3]='b'
table_x[5]='c'
for index,ele in generate(table_x) do
kaka(index,ele)
end
print('----------华丽的分割线-----------')
for index,ele in generate2(table_x) do
kaka(index,ele)
end




来个有用些的例子:



module('walkdir',package.seeall)
require'lfs'


local sep = "//"
function walkdir (path)
local i = 1
for file in lfs.dir(path) do
if file ~= "." and file ~= ".." then
local f = path..sep..file
--print ("/t=> "..f.." <=")
local attr = lfs.attributes (f)
assert (type(attr) == "table")
if attr.mode == "directory" then
coroutine.yield(file,path,attr)
walkdir (f)
else
coroutine.yield(file,path,attr)
end
end
end
end

function generate_dirwalker(path)
return coroutine.wrap(
function()
walkdir(path)
end
)
end
--test
function print_all(f,p,a)
print(string.format("%25s/t/t%s/t/t%s",f,p,a.mode))
end

for file,path,attr in generate_dirwalker('c://Downloads') do
print_all(file,path,attr)
end
--test




分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics