lua:关于本地范围的模块导入

时间:2013-05-23 13:36:48

标签: module lua scope embed local

有两个脚本文件包含以下脚本

//parent.lua
function scope()
    local var = "abc"

    require "child"
end

//child.lua
print(var)

这样,child.lua将打印一个nil值,因为parent.lua中的作用域不会将其本地功能公开给模块。我认为会这样,因为在此范围内和var声明之后陈述了require指令。我的愿望是将孩子的所有行完全注入父母。只是导出子脚本以提高可读性。我如何通过本地范围? loadfile()不起作用,也没有dofile()。函数环境fenv不包含本地值。 debug.setlocal()似乎无法创建新变量(也需要子进程中的接收器)。除了重新编译脚本之外的任何方法?

1 个答案:

答案 0 :(得分:2)

你可以付出一点努力。如果child中的变量是实际上升值,则可以将它们“链接”到scope函数中的值。如果它们是全局变量(这里似乎就是这种情况),您可以使用setfenv将它们映射到环境,并使用本地变量中的值填充该环境。

以下内容将按照您的预期打印abc(您可以将loadstring更改为loadfile,效果相同):

function vars(f)
  local func = debug.getinfo(f, "f").func
  local i = 1
  local vars = {}
  while true do
    local name, value = debug.getlocal(f, i)
    if not name then break end
    if string.sub(name, 1, 1) ~= '(' then vars[name] = value end
    i = i + 1
  end
  i = 1
  while func do -- check for func as it may be nil for tail calls
    local name, value = debug.getupvalue(func, i)
    if not name then break end
    vars[name] = value
    i = i + 1
  end
  return vars
end

function parent()
  local var = "abc"

  local child = loadstring("print(var)")

  local env = vars(2) -- grab all local/upvalues for the current function
  -- use these values to populate new environment; map to _G for everything else
  setmetatable(env, {__index = _G})
  setfenv(child, env)

  child()
end

parent()

这完全适用于Lua 5.1,但在Lua 5.2中也是如此。