关于lua corountine的困惑';s恢复与屈服函数
我通过这个学习lua,它有一段代码:关于lua corountine的困惑';s恢复与屈服函数,lua,coroutine,Lua,Coroutine,我通过这个学习lua,它有一段代码: co = coroutine.create(function() for i=1,5 do print(coroutine.yield(i)) end end) print(coroutine.resume(co,1,2)) print(coroutine.resume(co,3,4)) print(coroutine.resume(co,5,6)) print(coroutine.resume(co,7,8)) print
co = coroutine.create(function()
for i=1,5 do
print(coroutine.yield(i))
end
end)
print(coroutine.resume(co,1,2))
print(coroutine.resume(co,3,4))
print(coroutine.resume(co,5,6))
print(coroutine.resume(co,7,8))
print(coroutine.resume(co,9,10))
print(coroutine.resume(co,11,12))
输出如下:
true 1
3 4
true 2
5 6
true 3
7 8
true 4
9 10
true 5
11 12
true
但我不明白yield和resume是如何相互传递参数的,为什么yield不输出resume传递给它的第一个1,2,有人能解释一下吗?谢谢正常的Lua函数有一个入口(传入参数)和一个出口(传出返回值): 通过将参数放在括号内,将参数名(局部变量)绑定到参数名上,可以通过将函数调用表达式放在赋值语句的右侧或较大表达式(例如,另一个函数调用)内来检索作为
return
语句一部分列出的返回值
调用函数还有其他方法。例如,pcall()。通过将参数作为参数放入pcall()
函数调用(函数本身之后)来传递参数pcall()
还预加一个额外的返回值,该值指示函数是正常退出还是通过错误退出。被调用函数的内部是不变的
print( "f returned", pcall( f, 1, 2 ) )
--> arguments 1 2
--> f returned true I'm done
您可以使用coroutine.resume()
而不是pcall()
来调用协同程序的主函数。参数的传递方式和额外的返回值保持不变:
local th = coroutine.create( f )
print( "f returns", coroutine.resume( th, 1, 2 ) )
--> arguments 1 2
--> f returns true I'm done
但是使用协同路由,您可以(暂时)退出函数:coroutine.yield()
。通过将值作为参数放入yield()
函数调用中,可以通过coroutine.yield()
传递值。这些值可以作为coroutine.resume()
调用的返回值而不是正常的返回值在外部检索
但是,您可以通过再次调用coroutine.resume()
重新输入生成的协同路由。协同路由在其停止的位置继续,传递给coroutine.resume()
的额外值可作为之前挂起协同路由的yield()
函数调用的返回值
local function g( a, b )
print( "arguments", a, b )
local c, d = coroutine.yield( "a" )
print( "yield returned", c, d )
return "I'm", "done"
end
local th = coroutine.create( g )
print( "g yielded", coroutine.resume( th, 1, 2 ) )
print( "g returned", coroutine.resume( th, 3, 4 ) )
--> arguments 1 2
--> g yielded true a
--> yield returned 3 4
--> g returned true I'm done
请注意,产量不需要直接位于协同程序的主函数中,它可以位于嵌套函数调用中。执行跳回coroutine.resume()
,它首先(重新)启动了coroutine
现在问一下为什么第一个resume()
中的1,2
没有出现在输出中:您的coroutine main函数没有列出任何参数,因此会忽略传递给它的所有参数(在第一个函数条目上)。类似地,由于main函数不返回任何返回值,因此最后一个resume()
除了指示成功执行的true
之外,不会返回任何额外的返回值
co = coroutine.create(function()
for i=1,5 do
print(coroutine.yield(i))
end
end)
我们第一次启动协同程序时使用:
print(coroutine.resume(co,1,2))
它将一直运行到第一个产量。我们的第一个resume调用将返回true和yield参数(这里i=1),这解释了第一个输出行
我们的合作现在暂停。一旦我们再次呼叫resume:
print(coroutine.resume(co,3,4))
你的第一份简历最终会返回,你当前简历的参数(3,4)将被打印出来。第二次迭代开始时,调用coroutine.yield(2),这将再次使您的上一份简历返回true,依此类推
因此,实际上在您的示例中,coroutine.resume(co)对于第一次调用就足够了,因为任何进一步的参数都会丢失。我们看到这种行为的原因很微妙,但它与“进入”和“退出”语句的不匹配有关。它还与匿名函数中调用print
和yield
的顺序有关
让我们想象一下print(coroutine.yield(i))
vs.迭代的执行图
在第一次迭代中,我们有coroutine.resume
pass1
和2
到coroutine。这是原点,因此我们不是从以前的
,而是匿名函数本身的原始调用。在打印内部调用yield
,返回i=1
,但不调用print
。函数退出
接下来是在我们看到下一个coroutine.resume
恢复之前,函数暂停一段时间。此resume
通过3
和4
。函数在最后一次生成时拾取
。请记住,print
函数未被调用,因为第一个yield
首先被调用并退出程序?执行在print
中返回,因此现在调用print
,但这次返回3
和4
,因为这是要传递的最新值。该函数再次重复,在print
之前调用yield
,返回i=2
如果我们继续迭代,我们将更明确地了解为什么我们没有看到1
和2
的基本模式。我们的第一次迭代是“退出”收益率与相应的“进入收益率”不成对。这对应于第一次执行协程co
我们可能期望最后一个收益率
也不成对,但不同的是,我们将有一个“进入”收益率
,它是不成对的,而不是一个“退出”收益率
,它是不成对的。这是因为循环已经完成。这解释了为什么我们看到11 12
后面跟着true
,后面没有“退出”yield
return
这种情况与内部for循环的奇偶性(偶数/奇数)无关。唯一重要的是简历<
print(coroutine.resume(co,3,4))