Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/lua/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Function 在lua中使用每个调用的不同参数重用协同路由_Function_Lua_Arguments_Coroutine - Fatal编程技术网

Function 在lua中使用每个调用的不同参数重用协同路由

Function 在lua中使用每个调用的不同参数重用协同路由,function,lua,arguments,coroutine,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.res

我发现重用曾经创建的
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

考虑一下。协同程序的工作方式是这样的。当您第一次
resume
它们时,传递给
resume
的参数将成为协同程序函数的参数。当协同程序
yield
s时,它传递给
yield
的参数将成为
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
s(但不是后续参数)。但是,一旦将其放入数组中,数组的长度将基于第一个
nil

使用
capture\u args
,由于
select
的一个鲜为人知的功能,您可以获得实际的参数计数。由于
unpack
能够在给定的范围内工作,即使范围超过了表的长度,您也可以有效地存储参数列表

通过将长度放入它返回的表中,我可能会使
capture_args
更聪明一些。但这对我来说已经足够好了


这里还有第二个问题:您在
dummyFunc
中让步,而
dummyFunc
似乎不明白如何处理
yield
的返回值(即:下一次
恢复
调用的参数)


尚不清楚您希望如何
dummyFunc
响应它。如果您想更改
dummyFunc
的参数,因为您在不知道
dummyFunc
的情况下恢复了它,那是不会发生的。

您看过本手册的章节了吗?它显示了一个非常类似的例子。我想这不是我想要的。
corroutine中的函数“内部”更改值(本质类型)。就我对代码的理解而言,通过
给出的变量并没有真正改变,而是产生了
(某种外在的)。我可能是错的,但是,如果是这样的话,为了清楚起见,您能否发布一个简单的示例?您是否希望能够将
数据
变量从外部更改为
dummyFunc
,而无需通过
coroutine.resume在中传递新值?您可能需要使用全局变量来实现这一点(假设偶数有效),这可能不是一个好主意/设计。不,我想(通过将值传递给
resume
)而不使用全局变量来更改
数据。这就是示例所做的。您有一个复杂的内部函数,不能捕获内部
收益率
的结果,只能捕获一个
恢复
传递的值。再看一遍例子。