Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/lua/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Indexing 现有索引的Lua-_新索引元方法?_Indexing_Lua_Metatable_Global Scope_Meta Method - Fatal编程技术网

Indexing 现有索引的Lua-_新索引元方法?

Indexing 现有索引的Lua-_新索引元方法?,indexing,lua,metatable,global-scope,meta-method,Indexing,Lua,Metatable,Global Scope,Meta Method,我最近了解到lua有美沙酮,我一直在玩弄它们,直到我想到一个主意:有没有可能用它们来避免在一张桌子上出现“重复”?我找了又找,到目前为止还找不到我要找的东西,所以我来了 因此,以下是我希望能够做到的,以及目的: 它将用于WoW插件编程。 我想制作一个工具,每当在全局范围内创建变量或函数时都会提示警告(避免使用它,因为可能与其他加载项发生命名冲突)。 另一件我想做的事情是重定向所有从表到表的传输。因此,当用户在全局范围内创建变量或函数时,工具将捕获该变量或函数,并将其存储在表中,而不是存储在_

我最近了解到lua有美沙酮,我一直在玩弄它们,直到我想到一个主意:有没有可能用它们来避免在一张桌子上出现“重复”?我找了又找,到目前为止还找不到我要找的东西,所以我来了

  • 因此,以下是我希望能够做到的,以及目的:
它将用于WoW插件编程。 我想制作一个工具,每当在全局范围内创建变量或函数时都会提示警告(避免使用它,因为可能与其他加载项发生命名冲突)。 另一件我想做的事情是重定向所有从表到表的传输。因此,当用户在全局范围内创建变量或函数时,工具将捕获该变量或函数,并将其存储在表中,而不是存储在_G中,每当用户试图从_G访问某个对象时,工具将首先在所述表中查找该对象;并且只作为备用方案使用。 这样,用户就不必担心正确的封装或命名,工具将为他解决所有问题

  • 我已经做到了:
我在G上设置了一个uu newindex元方法来捕获全局范围的变量和函数,并在加载插件的末尾删除了元方法,以避免其他插件使用它。 对于“中转的间接寻址”,我已经知道如何使用索引来尝试在尝试使用前给出存储在另一个表中的值

  • 我的问题是:
这很有效,但仅适用于_G中不存在的变量和函数。每当将值赋给_G表中已经存在的键时,它都不起作用(原因很明显)。我希望能够捕捉到这些情况,基本上不可能真正覆盖_G的内容,而是使用某种“过载”(但用户甚至不必知道)

  • 我尝试的是:
我试图钩住rawset,看看它是否被自动调用,但似乎不是

我在lua中找不到太多关于_G表的文档,主要是因为它的名字很短。我确信一定有什么东西存在于某个地方,我可能会利用这些信息以我想要的方式完成事情,但目前我只是有点不知所措,没有想法了。
所以,是的,我想知道是否有任何方法可以“捕获”所有“对rawset的隐式调用”,以便在让它完成任务之前进行一些检查。我收集到的信息表明,显然没有针对现有索引或其他内容的元方法,所以您知道任何方法吗?

尽管您在评论中得到了答案,但在Lua5.1中有更深刻的环境概念。环境是附加到函数的表,该函数在其中重定向其“全局”读写<代码>\u G只是对“全局”环境的引用,即主线程(主协程)的环境。它可以被清除为nil而没有不明显的影响,因为它只是一个变量,类似于
T={};T._T=T

具体来说,
\u G==getfenv(0)
,除非有人改变它的含义(参见参考资料了解它的参数)。加载脚本时,它将隐式绑定到全局环境。由于Lua的顶级作用域(也称为主块)只是一个匿名函数,因此它的环境可以随时反弹到任何其他表:

-- x.lua

local T = { }
local shadow = setmetatable({ }, { __index = getfenv(0) })

local mt = {
    __index = shadow,
    __newindex = function (t, k, v)
        -- while T is empty, this will be called every time you 'set global'
        -- do whatever you want here
        shadow[k] = v
        print(tostring(k)..' is set to '..tostring(v))
    end
}

setmetatable(T, mt) -- T[k] goes to shadow, then to _G
setfenv(1, T)       -- change the environment of this module to T

hello = "World"     -- 'hello is set to World'
print(T.hello)      -- 'World'
print(_G.hello)     -- 'nil', because we didn't even touch _G

hello = 3.14        -- 'hello is set to 3.14'
hello = nil         -- 'hello is set to nil'
hello = 2.72        -- 'hello is set to 2.72'

function f()        -- 'f is set to function: 0x804a00'
    print(hello)
end

f()                 -- '2.72'

assert(getfenv(f) == getfenv(1))
assert(getfenv(f) == T)

setfenv(f, _G)      -- return f back to _G
f()                 -- 'nil'
通过这种方法,您可以对其他模块完全隐藏元表机制。请注意,对
mt
的更改在调用
setmetatable()
后无效

还请记住,下面定义的所有函数
setfenv()
共享相同的环境
T
(这不适用于通过
require
加载或从这些函数/模块返回的外部函数/模块,因为环境继承是词法性的)


\u G
上临时设置
\uu newindex
可能会起作用,但请记住,您在其间调用的任何函数都可能试图设置全局变量,这可能会干扰您的逻辑或以微妙的方式破坏它们的逻辑。冲突的可能性应该很低,因为破坏
\u G
是一个坏主意,每个人都知道这一点。

您正在寻找的是一个代理表。您需要创建一个新的空表并将其分配给
\u G
,同时将
\uu newindex
\uu index
设置为搜索原始
\u G
表的函数,该表以某种方式捕获。您的
\uuu newindex
函数不应允许重新定义现有键。我从来没有做过这样的事情,所以我不能告诉你这样的解决方案有多稳定。这肯定会非常缓慢。如果你愿意,我可以写一篇完整的文章。编辑:查看
strict.lua的实现以获得灵感。感谢您的回答;然而,我不确定它将如何解决我的问题。能够知道密钥是否已经存在于_G中不是问题(我可以简单地在工具的文件中有一个本地_G,并检查本地_G[key]~=nil);问题是我不知道如何知道已经存在的密钥何时被重新分配。我的工具的目标是“初始化并忘记”。我不希望在尝试将某个对象分配给全局范围时调用函数,我希望工具在我执行操作时“检测”,这样它就可以告诉我不要执行该操作。如果能够在每次将某个对象声明为全局时将其放入与_G不同的表中,那就太好了。我知道我可以通过在每个文件的开头获取一个本地“假”来实现这一点,但我希望避免这样做。值得注意的是,一个表现良好的插件应该返回一个库表,而不是创建全局变量。对于解释器,全局赋值
a=1
看起来像
\G['a'