在lua

时间:2015-09-17 09:56:59

标签: function lua arguments coroutine

我发现重用一次创建的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吗?

1 个答案:

答案 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知道它的方式而改变,那就不会发生。