我发现重用一次创建的协程非常有用.我找到了一个解决方案,它看起来像这样:
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的参数吗?
最佳答案 想想这个.协同程序的工作方式是这样的.当你第一次恢复它们时,你传递给恢复的参数成为协同程序函数的参数.当协同程序产生时,它传递给yield的参数将成为恢复调用的返回值.
但是,第二次恢复协程时,它不会进入仍在执行的函数并更改第一次传递的参数.改变函数局部变量的值是非常粗鲁的.
因此,第一次调用后在调用时恢复的参数将是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值. …将记录所有参数,甚至是嵌入的nils(但不是尾随的nils).但是,一旦将其放入数组中,数组的长度将基于第一个nil值.
使用capture_args,您可以获得实际参数计数,这要归功于select的一个鲜为人知的功能.并且由于解压缩能够在给定范围内工作,即使范围超出了表的长度,您也可以有效地存储参数列表.
我可以通过在它返回的表中放置长度来使capture_args更聪明一些.但这对我来说已经足够了.
这里有第二个问题:你在dummyFunc中屈服,而dummyFunc似乎不明白如何处理yield的返回值(即:你下一次恢复调用的参数).
目前尚不清楚你希望dummyFunc如何响应它.如果你想让dummyFunc的参数改变,因为你在没有dummyFunc了解它的情况下恢复它,那就不会发生.