【问题标题】:lua coroutine as iterator: cannot resume dead coroutinelua协程作为迭代器:无法恢复死协程
【发布时间】:2015-12-17 02:56:16
【问题描述】:

那里,

我修改了 Lua 5.0 在线文档中的“perm”示例:http://www.lua.org/pil/9.3.html。我所做的是将 __call() 元方法重新指向 perm() 函数。但它只工作一次,并报告“无法恢复死协程”。知道为什么它不起作用吗?

function permgen (a, n)
  if n == 0 then
 coroutine.yield(a)
  else
    for i=1,n do

      -- put i-th element as the last one
      a[n], a[i] = a[i], a[n]

      -- generate all permutations of the other elements
      permgen(a, n - 1)

      -- restore i-th element
      a[n], a[i] = a[i], a[n]

    end
  end
end

function perm (a)
  local n = table.getn(a)
  return coroutine.wrap(function () permgen(a, n) end)
end

K = {"a","b","c"}


for p in perm(K)  do
   print(p[1],p[2],p[3])
end


for p in perm(K)  do
   print(p[1],p[2],p[3])
end

-- everything above is copied from the Lua online document,
-- my modification is the following
setmetatable(K,{__call=perm(K)})
for p in K  do
   print(p[1],p[2],p[3])
end

-- cannot repeat!
-- perm.lua:44: cannot resume dead coroutine
for p in K  do
   print(p[1],p[2],p[3])
end

`

【问题讨论】:

  • 您将__call 设置为调用perm(K)结果。您的意思是让__call 实际上调用 perm 函数吗?

标签: lua iterator coroutine


【解决方案1】:

发生这种情况是因为您调用了一次perm(K) 并将结果分配给__call 元方法。然后您使用一次(通过执行in K)并完成由perm 调用返回的协程的执行。当你第二次尝试时,协程已经“死”了,这会触发错误。

你需要做的是检测协程是否已经死亡并重新创建它。由于您无法使用coroutine.wrap 执行此操作,因此您需要使用使用coroutine.create 的解决方案的略微修改版本。这样的事情可能会奏效:

function perm (a)
  local n = table.getn(a)
  local co = coroutine.create(function () permgen(a, n) end)
  return function ()   -- iterator
    if coroutine.status(co) == 'dead' then co = coroutine.create(function () permgen(a, n) end) end
    local code, res = coroutine.resume(co)
    if not code then return nil end
    return res
  end
end

它在恢复之前检查协程的状态,如果它已经是dead,那么它会使用相同的参数从头开始重新创建它。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-11-04
    • 2019-01-14
    • 1970-01-01
    • 1970-01-01
    • 2013-10-31
    • 2019-11-26
    • 2015-01-23
    相关资源
    最近更新 更多