function – 在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

那么可以在恢复调用之间更改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了解它的情况下恢复它,那就不会发生.

点赞