Recursion Lua在递归函数中声明局部变量

Recursion Lua在递归函数中声明局部变量,recursion,lua,scope,luaxml,Recursion,Lua,Scope,Luaxml,我刚开始编程,选择lua编写一个处理XML配置文件的脚本 我用LuaXML(C绑定版本)加载XML文件,它将XML文件映射到一个嵌套很重的表 当我试图编写一个函数来查找xmltable中标记的所有匹配项时,出现了我的问题。匹配项插入到函数返回的表中。我的问题是这个表变量的声明,它必须是函数的局部变量 首先,我尝试: local result = result or {} 但这会在每次递归时声明变量 最后,我提出了一个可行的解决方案,但对我来说太复杂了: function findall_wra

我刚开始编程,选择lua编写一个处理XML配置文件的脚本

我用LuaXML(C绑定版本)加载XML文件,它将XML文件映射到一个嵌套很重的表

当我试图编写一个函数来查找xmltable中标记的所有匹配项时,出现了我的问题。匹配项插入到函数返回的表中。我的问题是这个表变量的声明,它必须是函数的局部变量

首先,我尝试:

local result = result or {}
但这会在每次递归时声明变量

最后,我提出了一个可行的解决方案,但对我来说太复杂了:

function findall_wrapper(xmltable, tag)

  local results = {}

  function findall(xmltable, tag)

    if xml.TAG == tag then table.insert (results, xmltable) end

    for k, v in pairs(xmltable) do
      if (type(v) == "table") then findall(v, tag) end 
    end
  end

  findall(xmltable, tag)
  return results

end
我怎样才能以更好、更优雅的方式解决这个问题? 为什么
local result=result或{}
每次递归都声明变量


很抱歉,如果我的问题的答案太明显,但正如我所提到的,我刚刚开始编程

事实上,我认为你已经想出了一个漂亮而优雅的解决方案。您所做的是利用Lua中的函数,这在编写递归函数时是非常有用的技术,它需要在运行时构建数据结构。要使其完美,只需在
函数findall
内的
函数findall_包装器
前面添加local关键字,那么您的助手函数将是本地的,并且不会污染全局命名空间

详细说明一下:

有两种不同类型的函数,简单递归函数和复杂递归函数。所有递归函数都可以通过以下方式实现:

function sum_list(l)
  if #l == 0 then
    return 0
  else
    local e = table.remove(l)
    return e + sum_list(l)
  end
end

print(sum_list({1,2,3,4}))
> 10
在这里,调用堆栈用于存储中间结果,这可以为您提供一个非常大的堆栈,具有深度递归或对返回中的函数进行多次调用

更好的方法是:

在本例中,在调用中传递累加器,因此调用堆栈不再用于存储,如果实现支持它,它可以将其转换为迭代。遗憾的是,并非所有递归函数都是尾部递归的。在这种情况下,累加器的问题是人们必须将其实例化为零,否则它会给出错误的结果

解决这个问题的方法就是你所做的:

function sum_list(l)
  local function sum_list_helper(l, a)
    if #l == 0 then
      return a
    else
      local e = table.remove(l)
      return sum_list_helper(l, a + e)
    end
  end

  return sum_list_helper(l, 0)
end

创建一个本地函数,然后用正确的实例化值调用它。

如果您的意思是不想使用包装器函数,那么我认为您非常接近。这就是你的目标吗

function findall(xmltable, tag, results)
    local results = results or {}
    if xmltable[xml.TAG] == tag then table.insert(results, xmltable) end
    for k, v in pairs(xmltable) do
      if type(v) == "table" then findall(v, tag, results) end
    end
    return results
end

sum_list和sum_list_helper都是全局的。任何一个都可以是本地的,汇总列表帮助应该是本地的。Ups,忘记了本地关键字,非常感谢您的解释。非常有帮助。是的,当然!这正是我所缺少的。我必须将变量传递给递归函数。谢谢我测试了这两种解决方案的性能。使用包装器函数的原始版本速度更快。有趣。
function findall(xmltable, tag, results)
    local results = results or {}
    if xmltable[xml.TAG] == tag then table.insert(results, xmltable) end
    for k, v in pairs(xmltable) do
      if type(v) == "table" then findall(v, tag, results) end
    end
    return results
end