所需值的完整路径 [英] Full path to the required value
问题描述
如何获取表中所需值的完整路径?我想通过代理表跟踪另一个表中的变化.
How do I get the full path to the required value in the table? I want to track changes in another table through a proxy table.
我知道我需要在其中使用元表和__index.但是我还没有想出一个跟踪器.
I understand that I need to use metatables and __index in it. But I haven't been able to come up with a tracker yet.
示例表结构:
Objects = {
Panel = { layer = 1, x = 600, y = 328, w = 331, h = 491;
objects = {
label = { layer = 1, x = 0, y = 0, text = 'header' };
Window = { layer = 2, x = 400, y = 100, w = 100, h = 100;
objects = {
label = { layer = 1, x = 0, y = 0, text = 'lorem ipsum dorem' };
};
};
};
};
};
路径:Objects.Panel.objects.Window.objects.label.text
Path: Objects.Panel.objects.Window.objects.label.text
我试图为每个表创建一个元表并将每个对__index的调用的结果收集到一个表中,以便大致了解检索或更改了哪些键和值,以便将这些值与其他表同步
I tried to create a metatable for each of the tables and collect the result of each call to __index into a table in order to roughly understand which key and value were retrieved or changed in order to synchronize these values with other tables.
推荐答案
这将证明其运行缓慢且内存效率低下.无论如何,您是正确的:代理并根据自己的喜好处理 __ index
和 __ newindex
元方法.话虽如此,您还需要以某种方式跟踪代理的状态.
This will prove itself to be horrendously slow and memory inefficient. Anyway, you were right on the track: proxy and handle __index
and __newindex
metamethods to your liking. This being said you also need to track the state of the proxy somehow.
您可以尝试使用一些闭包和高值来隐藏它,但是简单的方法是将信息直接存储在代理表中:
You can try to hide it with some closures and upvalues but the easy way is to store the information directly in the proxy tables:
function make_tracker (o, name)
local mt = {}
mt.__index = function (proxy, key)
local path = {unpack(rawget(proxy, "__path"))} -- Stupid shallow copy
local object = rawget(proxy, "__to")
table.insert(path, key)
if type(object[key]) == "table" then
return setmetatable({__to = object[key], __path = path}, mt)
else
return table.concat(path, ".") .. " = " .. tostring(object[key])
end
end
return setmetatable({__to = o, __path = {name}}, mt)
end
__ to
字段指示代理应该指向哪个代理,并且 __ path
可以覆盖到目前为止我们已经侵入的字段.它会进行浅表复制,以便可以使用具有局部变量的子代理.参数 name
用于初始化第一个表的名称,因为您根本不知道这一点.您可以这样使用它:
__to
fields indicates what proxy should point to and __path
is there to cover fields we have trespassed so far. It does a shallow copy, so that one can use subproxies with local variables. name
parameter is there to initialize the name of the first table, as you just simply can't know that. You use it like this:
local tObjects = make_tracker(Objects, "Objects")
local subproxy = tObjects.Panel.objects.Window
print(subproxy.objects.label.text)
print(tObjects.Panel.objects.label.text)
print(subproxy.x)
-- prints:
-- Objects.Panel.objects.Window.objects.label.text = lorem ipsum dorem
-- Objects.Panel.objects.label.text = header
-- Objects.Panel.objects.Window.x = 400
当然,我怀疑您想要的是将路径附加到原始值.修改 else
块的内部:
Of course, I doubt that appending the path to the original value is what you want. Modify insides of else
block:
return table.concat(path, ".") .. " = " .. tostring(object[key])
根据您的需求,例如:
register_tracked_path(table.concat(path, "."))
return object[key]
如果要处理值的修改,则需要使用类似的 __ newindex
扩展元表.
If you want to handle modification of values you need to extend the metatable with similar __newindex
.
这篇关于所需值的完整路径的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!