我发现重用一次创建的coroutine
非常有用。我找到了一个解决方案,它看起来像这样:
co = coroutine.create(function (f, args)
while f do
f = coroutine.yield(f(args))
end
end)
function dummyFunc(data)
print("XXX "..data)
coroutine.yield()
print("OOO "..data)
end
coroutine.resume(co, dummyFunc, "1")
coroutine.resume(co, dummyFunc, "2")
coroutine.resume(co, dummyFunc, "3")
coroutine.resume(co, dummyFunc, "4")
除了输出之外,它就像魅力一样不:
XXX 1
OOO 2
XXX 3
OOO 4
是:
XXX 1
OOO 1
XXX 1
OOO 1
那么可以在恢复调用之间将参数更改为dummyFunc
吗?
答案 0 :(得分:2)
想一想。协同程序的工作方式是这样的。当您第一次resume
时,传递给resume
的参数将成为协程函数的参数。当协程yield
时,它传递给yield
的参数将成为resume
来电的返回值。
但是,第二次你{/ 1}}协程,它不会进入仍在执行的函数并更改第一次传递的参数。改变函数局部变量的值是非常粗鲁的。
因此,{/ 1}}在第一次调用后调用时的参数将是来自resume
的返回值。
resume
所以你需要这样做:
yield
但是,如果你想要更灵活的东西,可以做不同数量的参数,你需要更聪明:
co = coroutine.create(function (f, args)
while f do
f = coroutine.yield(f(args))
end
end)
有些人不会理会co = coroutine.create(function (f, args)
while f do
f, args = coroutine.yield(f(args))
end
end)
内容,只需依靠co = coroutine.create(function (...)
local function capture_args(...)
return {...}, select("#", ...)
end
local tbl, len = capture_args(...)
local f = tbl[1]
while f do
tbl, len = capture_args(coroutine.yield(f(unpack(tbl, 2, len))
f = tbl[1]
end
end)
并在其上调用capture_args
即可。这样更安全,因为用户可以将{...}
值放在参数列表中。 unpack
将记录所有参数,甚至是嵌入的nil
(但不是尾随的)。但是,一旦将其放入数组中,数组的长度将基于第一个...
值。
使用nil
,您可以获得实际参数计数,这要归功于nil
的一个鲜为人知的功能。并且由于capture_args
能够处理给定范围,即使范围超出表的长度,您也可以有效地存储参数列表。
我可以通过将长度放在它返回的表中来使select
更聪明一些。但这对我来说已经足够了。
这里有第二个问题:你在unpack
内屈服,capture_args
似乎不明白如何处理dummyFunc
的返回值(即:参数为你的下一个dummyFunc
电话。
目前尚不清楚您希望yield
如何回应它。如果您希望resume
的参数因您恢复而 dummyFunc
知道它的方式而改变,那就不会发生。