As part of a project I was working on, I wanted to be able to print out whenever a table is accessed or written to, and what was accessed/written to in the table. Looking this up, I found this, which described how to track whenever a table is accessed/updated by using a proxy table and the __index
and __newindex
metamethods. However, the code they provide does not properly display what is going on if a nested table is used as the proxy table. Suppose I write the following code, adapted from the previous one:
mt = {}
function mt.__index(self, key)
print('accessing key '..key)
return self.proxy[key]
end
function mt.__newindex(self, key, value)
print('setting key '..key..' to value '..tostring(value))
self.proxy[key] = value
end
function setproxy(t)
new_t = {proxy = t}
setmetatable(new_t, mt)
return new_t
end
t = {
a = 1,
b = 2,
c = {
a = 3,
b = 4,
},
}
t = setproxy(t)
t.a = 2 -- prints "setting key a to value 2" as expected
t.c.a = 4 -- prints "accessing key c", nothing else
The problem here is that __index
is called to access the key c
and it returns a value in the proxy table, but that doesn't have the same metatable so it doesn't log the write to t.c
. I would like for the second assignment to print something like setting key c.a to value 4
, but I'm not really sure where to start on actually implementing such a thing.
After a lot of thought, I think you might be able to do it by having each key that has a table value also be another proxy table, but then you have to
- recursively replace all table values with proxy tables, and I was
thinking each proxy table would include some info that allows
__newindex
for this proxy table to print out the correct key - if some key is set to a table value, you have to recursively replace it with proxy tables before you can set the actual value
and that just seems like so much work and complication for something that should be simpler than this.