博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
对lua协程的一点理解
阅读量:4307 次
发布时间:2019-06-06

本文共 2293 字,大约阅读时间需要 7 分钟。

读《Programming In Lua》协程那一章,比较困惑的还是procuer-consumer那个例子:

function consumer(prod)    while true do        local x = receive(prod)        print(x)    endendfunction receive(prod)    local status, value = coroutine.resume(prod)    return valueendfunction send(x)    coroutine.yield(x) -- go back to where resumedendfunction producer()    return coroutine.create(function()        while true do            local x = io.read()            send(x)        end    end)end-- consumer-driven designconsumer(producer())

producer产生数据,consumer消费数据,producer与consumer都在各自的协程中完成, 代码很短,但是很难读 - 至少不是那么一目了然,尤其比起这个直接的循环:

function produce()    return io.read()endfunction consume(x)    print(x)endwhile true do    local x = produce()    consume(x)end

好在哪里?

书中说可以添加缓存控制速度,或者进行数据过滤 - 但是这在循环版本的producer-consumer中也都能做到,无非在在实现produce是多些逻辑,或者再加个filter的函数处理produce的返回值,协程版本毫无优势可言。

实在要说其优点,恐怕只是:producer和consumer的代码在各自的协程中实现,并通过resume-yield交换数据 - 实现了松耦合。这是个优点,可以还是不太满意,再往下看时,看到了全排列那个例子,稍作修改,让我比较直观的感觉到了协程这种控制结构的灵活性:

function send(a)    coroutine.yield(a)endfunction receive(prod)    local status, value = coroutine.resume(prod)    return valueendfunction consumer(prod)    local function print_result(a)        for _, v in ipairs(a) do            io.write(v, " ")        end        io.write('\n')    end        while true do        local a = receive(prod)        if not a then break end        print_result(a)    endendfunction producer(a)    function permgen(a, n)        if n == 0 then            send(a) -- send something for consuming from an recursive call        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    local n = table.getn(a)    return coroutine.create(function() permgen(a, n) end)endconsumer(producer({
1,2,3,4}))

这里全排列采用了递归算法:对数组中的每个元素,把它交换到数组末尾,然后对前n-1个元素的子数组做同样的事,当n==0时,输出一个排列。

这个在produce的时候,因为在一个递归调用中,你无法一个个返回:

  • 要么每找到一个,直接在里面处理 - 这样produce-consume的结构就有点混淆在一起;
  • 或者先把结果保存在一个共享内存中,产生全部排列后,再逐个处理 - 这样要另外开辟空间,流程上感觉也不够简洁。

于是,协程的有点就显现出来了,不同于简单函数中的return,协程可以在找到一个排列后,yield挂起本协程并返回该排列,返回到原来resume这个协程的代码处,取得数据进行consume,然后继续resume进入协程获取排列 - 通过协程灵活控制流程并传递数据,十分漂亮。

所以,那个循环版本的问题是:并不是所有produce的数据,都可以简单的return回来的。

转载于:https://www.cnblogs.com/baiyanhuang/archive/2012/11/17/2775315.html

你可能感兴趣的文章
设计模式11_装饰器
查看>>
设计模式12_外观模式
查看>>
设计模式13_享元模式
查看>>
设计模式14_组合结构
查看>>
设计模式15_模板
查看>>
海龟交易法则01_玩风险的交易者
查看>>
CTA策略02_boll
查看>>
vnpy通过jqdatasdk初始化实时数据及历史数据下载
查看>>
设计模式19_状态
查看>>
设计模式20_观察者
查看>>
vnpy学习10_常见坑02
查看>>
用时三个月,终于把所有的Python库全部整理了!拿去别客气!
查看>>
pd.stats.ols.MovingOLS以及替代
查看>>
vnpy学习11_增加测试评估指标
查看>>
资金流入流出计算方法
查看>>
海龟交易法则07_如何衡量风险
查看>>
海龟交易法则08_风险与资金管理
查看>>
海龟交易法则09_海龟式积木
查看>>
海龟交易法则10_通用积木
查看>>
海龟交易法则14_掌控心魔
查看>>