在lua中,每次调用使用不同的参数重用协程



我发现重用一次创建的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不知道的情况下恢复它而更改,那么这将不会发生。

最新更新