5

有以下两个脚本文件

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

    require "child"
end

//child.lua
print(var)

这样,child.lua 将打印一个 nil 值,因为 parent.lua 中的范围不会将其本地特性暴露给模块。我认为会的,因为 require 指令是在这个范围内并且在声明 var 之后声明的。我的愿望是实际上将孩子的所有台词完全注入父母。子脚本只是为了更好的可读性而导出的。如何通过本地范围?loadfile() 不起作用,dofile() 也不起作用。函数环境 fenv 不包含本地值。debug.setlocal() 似乎无法创建新变量(也需要在子节点中有接收器)。除了重新编译脚本还有什么方法吗?

4

1 回答 1

2

你可以稍加努力。如果您的变量child是真正的上值,您可以将它们“链接”到scope函数中的值。如果它们是全局变量(这里似乎就是这种情况),您可以将它们映射到使用setfenv局部变量的值并使用该环境填充的环境。

以下将abc按照您的预期打印(您可以更改loadstringloadfile具有相同的效果):

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 中也是可能的。

于 2013-05-23T23:22:51.800 回答