当前位置: 首页 > 编程笔记 >

Lua 创建和使用协程

岳俊晖
2023-03-14
本文向大家介绍Lua 创建和使用协程,包括了Lua 创建和使用协程的使用技巧和注意事项,需要的朋友参考一下

示例

与协程互动的所有功能在协程表中都可用。通过使用带有单个参数的coroutine.create函数来创建新的协:一个具有要执行的代码的函数:

thread1 = coroutine.create(function()
            print("honk")
        end)

print(thread1)
-->> thread: 6b028b8c

协程对象返回代表新协程的thread类型的值。创建新的协程时,其初始状态将被暂停:

print(coroutine.status(thread1))
-->> suspended

要恢复或启动协程,函数和coroutine.resume时,给定的第一个参数是线程对象:

coroutine.resume(thread1)
-->> honk

现在协程执行代码并终止,将其状态更改为dead,至此无法恢复。

print(coroutine.status(thread1))
-->> dead

Coroutines can suspend its execution and resume it later thanks to the coroutine.yield function:

thread2 = coroutine.create(function()
        for n = 1, 5 do
            print("honk "..n)
            coroutine.yield()
        end
    end)

As you can see, coroutine.yield() is present inside the for loop, now when we resume the coroutine, it will execute the code until it reachs a coroutine.yield:

coroutine.resume(thread2)
-->> honk 1
coroutine.resume(thread2)
-->> honk 2

After finishing the loop, the thread status becomes dead and cannot be resumed. Coroutines also allows the exchange between data:

thread3 = coroutine.create(function(complement)
    print("honk "..complement)
    coroutine.yield()
    print("再次鸣喇叭 "..complement)
end)
coroutine.resume(thread3, "stackoverflow")
-->> honk stackoverflow

If the coroutine is executed again with no extra arguments, the complement will still the argument from the first resume, in this case "stackoverflow":

coroutine.resume(thread3)
-->> 再次鸣喇叭 stackoverflow

Finally, when a coroutine ends, any values returned by its function go to the corresponding resume:

thread4 = coroutine.create(function(a, b)
    local c = a+b
    coroutine.yield()
    return c
end)
coroutine.resume(thread4, 1, 2)
print(coroutine.resume(thread4))
-->> true, 3

Coroutines are used in this function to pass values back to a calling thread from deep within a recursive call.

local function Combinations(l, r)
    local ll = #l
    r = r or ll
    local sel = {}
    local function rhelper(depth, last)
        depth = depth or 1
        last = last or 1
        if depth > r then
            coroutine.yield(sel)
        else
            for i = last, ll - (r - depth) do
                sel[depth] = l[i]
                rhelper(depth+1, i+1)
            end
        end
    end
    return coroutine.wrap(rhelper)
end

for v in Combinations({1, 2, 3}, 2) do
    print("{"..table.concat(v, ", ").."}")
end
--> {1, 2}
--> {1, 3}
--> {2, 3}

协程也可以用于延迟评估。

-- slices a generator 'c' taking every 'step'th output from the generator
-- starting at the 'start'th output to the 'stop'th output
function slice(c, start, step, stop)
    local _
    return coroutine.wrap(function()
        for i = 1, start-1 do
            _ = c()
        end
        for i = start, stop do
            if (i - start) % step == 0 then
                coroutine.yield(c())
            else
                _ = c()
            end
        end
    end)
end


local alphabet = {}
for c = string.byte('a'), string.byte('z') do
    alphabet[#alphabet+1] = string.char(c)
end
-- only yields combinations 100 through 102
-- requires evaluating the first 100 combinations, but not the next 5311633
local s = slice(Combinations(alphabet, 10), 100, 1, 102)
for i in s do
    print(table.concat(i))
end
--> abcdefghpr
--> abcdefghps
--> abcdefghpt

协程可用于如Lua编程中所述的管道构造。PiL的作者Roberto Ierusalimschy也发表了一篇论文,内容涉及使用协程来实现更高级的通用流程控制机制,例如延续。

 类似资料:
  • 本文向大家介绍Lua 元表的创建和使用,包括了Lua 元表的创建和使用的使用技巧和注意事项,需要的朋友参考一下 示例 一个元表定义了一组改变lua对象行为的操作。一个元表只是一个普通的表,它以一种特殊的方式使用。            

  • 本文向大家介绍创建Lua虚拟机,包括了创建Lua虚拟机的使用技巧和注意事项,需要的朋友参考一下 示例 5.1 5.1            

  • 主要内容:什么是协同(coroutine)?,coroutine_test.lua 文件,实例,生产者-消费者问题,实例什么是协同(coroutine)? Lua 协同程序(coroutine)与线程比较类似:拥有独立的堆栈,独立的局部变量,独立的指令指针,同时又与其它协同程序共享全局变量和其它大部分东西。 协同是非常强大的功能,但是用起来也很复杂。 线程和协同程序区别 线程与协同程序的主要区别在于,一个具有多个线程的程序可以同时运行几个线程,而协同程序却需要彼此协作的运行。 在任一指定时刻只有

  • 什么是协同(coroutine)? Lua 协同程序(coroutine)与线程比较类似:拥有独立的堆栈,独立的局部变量,独立的指令指针,同时又与其它协同程序共享全局变量和其它大部分东西。 协同是非常强大的功能,但是用起来也很复杂。 线程和协同程序区别 线程与协同程序的主要区别在于,一个具有多个线程的程序可以同时运行几个线程,而协同程序却需要彼此协作的运行。 在任一指定时刻只有一个协同程序在运行,

  • 关于色板 色板是命名的颜色、色调、渐变和图案。与文档相关联的色板出现在 “色板 ”面板中。色板可以单独出现,也可以成组出现。可以打开来自其他 Illustrator 文档和各种颜色系统的色板库。色板库显示在单独的面板中,不与文档一起存储。 “色板 ”面板和色板库面板可包括以下类型的色板:印刷色印刷色使用四种标准印刷色油墨的组合打印:青色、洋红色、黄色和黑色。默认情况下, Illustrator 将

  • 本文向大家介绍sass 创建和使用混合,包括了sass 创建和使用混合的使用技巧和注意事项,需要的朋友参考一下 示例 要创建一个mixin,请使用@mixin指令。 您可以在mixin名称后面的括号内指定参数列表。切记以变量开头,$并用逗号分隔。 要在另一个选择器中使用mixin,请使用@include指令。 从混入样式将目前在使用footer,并header与值#ccc的$color变量,#dd

  • 一旦你知道如何输入SQL语句的时候,你就可以准备访问一个数据庫。 假设,在你家(你的menagerie)有一些宠物,并且你想对他们的信息保持一个跟踪。这时候,你可以创建表来存储和加载你渴望的信息。然后你就可以通过检索数据庫里的表来回答各种各样的问题,这部分展示如何执行以下操作: 创建数据庫 创建表 加载数据到表 以不同的方式从表中检索数据 使用多个表 menagerie数据庫是简单的,但不难想像到

  • 在owncloud相关网站和stackoverflow自身的以下链接中,所有相关信息都以不完整的形式呈现: 用户配置Api-Owncloud 我试着做一些非常简单的事情: > 我得到这样的输出: 开始处理凭据,首先它将存储在本地变量中 Hello Frank 您的密码是frankspassword failure 997未经授权 在owncloud中创建了一个新用户 我还尝试使用以下php脚本登录