Lua 5.2 元表和环境
Lua 5.2 metatables and environment
我有这样的结构:
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
函数中,就在设置 local _ENV
之后。这个用户输入的代码应该被沙盒化。它应该能够访问一些功能(context
table 中的功能)和其他模块的内容。 m1: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
来自哪里?
modules.m2.variables.x
没有得到更新,因为您只设置了 __index
metamethod (which is used when retrieving a non-existing key), but not __newindex
metamethod(在为不存在的键赋值时使用),结果该值存储在 modules.m2.x
table 而不是你想要的 modules.m2.variables.x
table。
如果我像 setmetatable(modules.m2, {__index = modules.m2.variables, __newindex = modules.m2.variables})
那样添加 __newindex
,我会得到预期的结果。
我有这样的结构:
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
函数中,就在设置 local _ENV
之后。这个用户输入的代码应该被沙盒化。它应该能够访问一些功能(context
table 中的功能)和其他模块的内容。 m1: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
来自哪里?
modules.m2.variables.x
没有得到更新,因为您只设置了 __index
metamethod (which is used when retrieving a non-existing key), but not __newindex
metamethod(在为不存在的键赋值时使用),结果该值存储在 modules.m2.x
table 而不是你想要的 modules.m2.variables.x
table。
如果我像 setmetatable(modules.m2, {__index = modules.m2.variables, __newindex = modules.m2.variables})
那样添加 __newindex
,我会得到预期的结果。