lua学习笔记四--协同程序

协同程序

协同程序基础

Lua 将所有关于协同程序的函数放置在一个名为 “coroutine” 的 table 中,函数 create 用于创建新的协同程序,它只有一个参数,就是一个函数。该函数的代码就是协同程序所要执行的内容。

co = coroutine.create(function() print("Hello world!") end)
print(co) -- thread: 0x80719d8

一个协同进程可能处于四种状态:挂起(suspended)、运行(running)、死亡(dead)和正常(normal)。create函数仅仅是创建协同进程,此时并没有运行,协同程序处于挂起状态,可使用 status 函数查看状态。

print(coroutine.status(co)) -- suspended

resume函数用于启动或者再次启动一个协同程序,由挂起状态变为运行

coroutine.resume(co) -- "Hello world!"

上面的协同程序只是简单的打印了一个 “Hello world!”,然后就结束了,此时协同程序处于死亡状态(dead),这种状态的协同程序是不能被再次唤醒的

print(coroutine.status(co)) -- dead
print(coroutine.resume(co)) -- false can not resume dead coroutine

coroutine.yield() 函数可以让程序挂起,resume函数可以恢复程序的运行。

当一个协同程序A唤醒另一个协同程序B时,A就处于正常状态。
注意:resume 是在保护模式下运行的,也就是说,当一个协同程序发生错误时,Lua并不会显示错误消息,而是将执行权返回给 resume 调用。


Lua 的 resume-yield 数据交换机制。

  • 第一次调用 resume 时,没有对应的 yield 等待,所有 resume 传入的额外参数都将作为协同程序主函数的参数。
co = coroutine.create(function(a, b) print("co", a, b) end)
coroutine.resume(co,1,2) -- co 1 2
resume调用额外传入的参数,作为协同程序主函数的参数,上例中的参数 a 和 b 就是这种情况 - 在 resume 调用返回的内容中,第一个值为 true 表示没有错误,后面所有值都是对应的 yield 传入的参数
co = coroutine.create(function(a, b)
    coroutine.yield(a+b, a-b)
    end)
print(coroutine.resume(co, 20, 10)) -- true 30 10

上例中resume 函数返回的值 30 和 20 ,都是 yield 函数传入的参数

  • yield 返回的额外值就是 resume 传入的参数
co = coroutine.create(function()
    print("co", coroutine.yield())
    end)
coroutine.resume(co)
coroutine.resume(co, 2, 4) -- co 4 5

yield函数返回的值,就是 resume 额外传入的参数,所以上例中 yield 函数汇返回 4 5, print 函数打印结果为 “co 4 5”

  • 当一个协同函数结束时,它的主函数返回值都将作为对应的 resume 函数的返回值
co = coroutine.create(function()
    return 3, 4
    end)
coroutine.resume(co) -- true 3 4

Lua提供的是一种“非对称的协同程序”,只有协同程序的主函数才能调用 yield 函数,让程序挂起


下面是使用协同程序实现一个去数组组合的例子,通过递归实现,并将程序写成迭代器的形式,访问所有可能的组合。

-- select k elements from set to subset
function comb(set, subset, n, k)
    if n < k then
        return
    end 

    if k==0 then
--      printResult(subset)
        coroutine.yield(subset)
        return
    else
        for i=n,k,-1 do
            subset[k] = set[i]
            if k>0 then
                comb(set, subset, i-1, k-1)
            end 
        end 
    end 
end

function printResult(set)
    n = n or #set
    for i=1,n do
        io.write(set[i], " ")
    end 
    io.write("\n")
end

---[[
function combination(set, subset, n, k)
    local co = coroutine.create(function()
        comb(set, subset, n, k)
    end)

    return function() -- 迭代器函数
        local state,res = coroutine.resume(co)
        return res
    end
end
--]]

set = {"a", "b", "c", "d", "e"}

subset = {}
--[[
comb(set, subset, 5, 4)
--]]

---[[
for p in combination(set, subset, 5, 3) do -- subset必须构造成 table ,否则会出错,显示访问的p为空
    printResult(p)
end
--]]

你可能感兴趣的:(学习总结,lua学习笔记)