2015-04-15 99 views
3

我有一個結構是這樣的:的Lua 5.2元表和環境

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}) 

的想法是,用戶輸入的代碼放到一個用戶界面和代碼粘貼到不同模塊的功能update剛結束其中設置了local _ENV。這個用戶輸入的代碼應該被沙箱化。它應該能夠訪問幾個函數(context表中的函數)和其他模塊的內容。 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.xmodules.m2.variables.x不同,那麼modules.m2.x是從哪裏來的?

回答

3

modules.m2.variables.x是沒有得到更新,因爲你只設置__index metamethod(這是檢索一個不存在的鍵時使用),但不__newindex metamethod(其值分配給一個不存在的鍵時使用),並作爲結果該值存儲在modules.m2.x表中,而不是您想要的modules.m2.variables.x表。

如果我在setmetatable(modules.m2, {__index = modules.m2.variables, __newindex = modules.m2.variables})中添加__newindex,我會得到預期結果。

+0

太棒了!謝謝! – Tom