在 Lua 中使用加载函数使变量在环境中可用

Making variables available inside environment with load function in Lua

这个问题对这个问题有一些参考。 以下代码工作正常。

    local function _implies(a, b)
      if a == 1 and b == 0 then return 0 
        else return 1 end
    end
    
    local my_right = {
        __mul = function(self, b)
            return _implies(self.a, b)
        end
      }
      
      local _mt =  {
        __mul = function(a)
            return setmetatable({a=a}, my_right)
        end
    }
    
    local my_left={}
    setmetatable(my_left,_mt)
    imp = my_left
    local names={}
    
    
    for i = 0,1 do
       for j=0,1 do
         names.i=i;names.j=j
       print(i, j, names.i *imp* names.j)
      
       end
    end

但是下面的代码不起作用。

str="i *imp* j"

local function _implies(a, b)
  if a == 1 and b == 0 then return 0 
    else return 1 end
end

local my_right = {
    __mul = function(self, b)
        return _implies(self.a, b)
    end
  }
  
  local _mt =  {
    __mul = function(a)
        return setmetatable({a=a}, my_right)
    end
}

local my_left={}
setmetatable(my_left,_mt)
imp = my_left
local names={}

for i = 0,1 do
   for j=0,1 do
     names.i=i; names.j=j
   print(i, j,  load("return " .. str,nil,"t",names)())
  
   end
end

它给出了 尝试对 nil 值(全局 'imp') 执行算术的错误。这可能是因为 imp 在名称环境中不可用。还是有其他原因?如何在环境名称中提供 imp

您将名称作为环境传递给加载函数。 names 中的元素因此作为您加载的块的全局环境。那不包含小鬼。要使其工作,请按如下方式定义名称:local names = { imp = imp }.

然后就可以了

另一种选择是使用 local names = {}; setmetatable(names, {__index = _G}) 来允许访问全局变量(直接在 names table 中的变量将“隐藏”全局变量)。 替换 names 时,您必须重新设置元 table。或者,不要替换“名称”环境,而只是更新 ij 字段:names.i = i; names.j = j