我发现重用一次创建的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
那么有可能在resume调用之间将参数更改为dummyFunc
吗?
考虑一下。协同程序的工作方式是这样的。当您第一次对它们进行resume
时,传递给resume
的参数将成为协程函数的参数。当协程yield
运行时,它传递给yield
的参数将成为resume
调用的返回值。
然而,当第二次 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
如何回应它。如果您希望dummyFunc
的参数因为您如何在 dummyFunc
不知道的情况下恢复它而更改,那么这将不会发生。