代码之家  ›  专栏  ›  技术社区  ›  Lorinc Nyitrai

Lua-将协程递归重写为尾部调用递归

  •  3
  • Lorinc Nyitrai  · 技术社区  · 7 年前

    coroutine .

    它创建了一个(路径、值)对数组,例如:。 {{key1, key2, key3}, value} value 你必须这么做 nested_table[key1][key2][key3]

    在那之后我写了 find() , findall() , in()

    function table.extend(tbl, new_value)
      local tbl = {table.unpack(tbl)}
      table.insert(tbl, new_value)
      return tbl
    end
    
    function iterate(tbl, parent)
      local parent = parent or {}
      if (type(tbl)=="table") then
        for key, value in pairs(tbl) do
          iterate(value, table.extend(parent, key))
        end
      end
      coroutine.yield(parent, tbl)
    end
    
    function traverse(root)
       return coroutine.wrap(iterate), root
    end
    

    然后我意识到我必须使用的Lua环境 协同程序 协同程序 .

    -- testdata
    
    local pool = {}
    test = {
      ['a'] = 1,
      ['b'] = {
        ['c'] = {2, 3},
        ['d'] = 'e'
      }
    }
    
    -- tree traversal
    
    function table.extend(tbl, element)
      local copy = {table.unpack(tbl)}
      table.insert(copy, element)
      return copy
    end
    
    local function flatten(value, path)
      path = path or {'root'}
      pool[path] = value -- this is the 'yield'
      if type(value) == 'table' then
        for k,v in pairs(value) do
          flatten(v, table.extend(path, k))
        end
      end
    end
    
    -- testing the traversal function
    
    flatten(test)
    
    for k, v in pairs(pool) do
      if type(v) == 'table' then v = '[table]' end
      print(table.concat(k, ' / ')..' -> '..v)
    end
    

    root -> [table]
    root / b / c / 1 -> 2
    root / b -> [table]
    root / a -> 1
    root / b / d -> e
    root / b / c / 2 -> 3
    root / b / c -> [table]
    

    pool ,此代码称为并行。我不能做正确的尾部调用递归( return flatten(...) )来自 for 循环,因为它只会返回一次。

    我试着让它成为一个物体,遵循这些模式 here ,但我无法让它工作。

    1 回复  |  直到 7 年前
        1
  •  6
  •   Egor Skriptunoff    7 年前

    你可以 pool 局部变量:

    test = {
       ['a'] = 1,
       ['b'] = {
          ['c'] = {2, 3},
          ['d'] = 'e'
       }
    }
    
    -- tree traversal
    
    function table.extend(tbl, element)
       local copy = {table.unpack(tbl)}
       table.insert(copy, element)
       return copy
    end
    
    local function flatten(value, path, pool)    -- third argument is the pool
       path = path or {'root'}
       pool = pool or {}                                    -- initialize pool
       pool[path] = value
       if type(value) == 'table' then
          for k,v in pairs(value) do
             flatten(v, table.extend(path, k), pool)  -- use pool in recursion
          end
       end
       return pool                           -- return pool as function result
    end
    
    -- testing the traversal function
    
    local pool = flatten(test)
    
    for k, v in pairs(pool) do
       if type(v) == 'table' then v = '[table]' end
       print(table.concat(k, ' / ')..' -> '..v)
    end