3

我有这样的结构:

context = {
  pi = math.pi,
  sin = math.sin,
  cos = math.cos,
  tan = math.tan,
  print = print
}

modules = {
  m1 = {
    variables = { x = 1 },
    update = function(self)
      local _ENV = self.variables
      x = 2
      m2.x = 2
    end
  },
  m2 = {
    variables = { x = 1 },
    update = function(self)
      local _ENV = self.variables
    end
  }
}

setmetatable(modules.m1, {__index = modules.m1.variables})
setmetatable(modules.m1.variables, {__index = context})

setmetatable(modules.m2, {__index = modules.m2.variables})
setmetatable(modules.m2.variables, {__index = context})

setmetatable(context, {__index = modules})

这个想法是用户在 UI 中输入代码,然后将代码粘贴到update不同模块的功能中,就在 wherelocal _ENV设置之后。这个用户输入的代码应该是沙盒的。它应该能够访问一些功能(context表中的功能)和其他模块的内容。代码 inm1:update应该能够在m1.variables不限定变量的情况下引用变量;其他模块中的变量(即 中的变量m2.variables)应该可以通过使用模块名称(即m2.x)限定它们来访问。

但我得到的结果是这样的:

$ lua -i test.lua
> = modules.m1.x
1
> = modules.m1.variables.x
1
> = modules.m2.x
1
> = modules.m2.variables.x
1
> = modules.m1:update()
> = modules.m1.x
2
> = modules.m1.variables.x
2
> = modules.m2.x
2
> = modules.m2.variables.x
1

为什么modules.m2.variables.x不更新了?如果看起来modules.m2.x与 不同modules.m2.variables.x,那么modules.m2.x来自哪里?

4

1 回答 1

3

modules.m2.variables.x没有得到更新,因为您只设置__index了元方法(在检索不存在的键时使用),而不是__newindex元方法(在将值分配给不存在的键时使用),结果值存储在modules.m2.x表而不是modules.m2.variables.x您想要的表。

如果我添加__newindexas in setmetatable(modules.m2, {__index = modules.m2.variables, __newindex = modules.m2.variables}),我会得到预期的结果。

于 2015-04-15T06:21:05.390 回答