Lua 如何记录嵌套表的访问/写入?

Lua 如何记录嵌套表的访问/写入?,lua,metatable,Lua,Metatable,作为我所从事项目的一部分,我希望能够在访问或写入表时打印出来,以及在表中访问/写入的内容。查找这个,我发现,它描述了如何通过使用代理表和\uuuu索引和\uu新索引元方法来跟踪何时访问/更新表。但是,如果将嵌套表用作代理表,则它们提供的代码无法正确显示发生的情况。假设我编写了以下代码,改编自上一个代码: mt={} 函数mt.\u索引(自、键) 打印('访问键'…键) 返回self.proxy[键] 结束 函数mt.\uu newindex(self、key、value) 打印('设置键'…键.

作为我所从事项目的一部分,我希望能够在访问或写入表时打印出来,以及在表中访问/写入的内容。查找这个,我发现,它描述了如何通过使用代理表和
\uuuu索引
\uu新索引
元方法来跟踪何时访问/更新表。但是,如果将嵌套表用作代理表,则它们提供的代码无法正确显示发生的情况。假设我编写了以下代码,改编自上一个代码:

mt={}
函数mt.\u索引(自、键)
打印('访问键'…键)
返回self.proxy[键]
结束
函数mt.\uu newindex(self、key、value)
打印('设置键'…键..'到值'…到字符串(值))
self.proxy[key]=值
结束
函数setproxy(t)
new_t={proxy=t}
可设置图元(新,mt)
返回新的
结束
t={
a=1,
b=2,
c={
a=3,
b=4,
},
}
t=setproxy(t)
t、 a=2——按预期打印“将键a设置为值2”
t、 c.a=4——打印“访问键c”,无其他内容
这里的问题是调用
\u index
来访问键
c
,它在代理表中返回一个值,但该表没有相同的元表,因此它不会记录对
t.c
的写入。我想在第二个作业中打印一些内容,比如
将键c.a设置为值4
,但我真的不确定从哪里开始实际实现这样的事情

经过深思熟虑后,我认为您可能可以通过让每个具有表值的键也成为另一个代理表来实现这一点,但是您必须这样做

  • 递归地用代理表替换所有表值,我 认为每个代理表都会包含一些允许
    \uuuu newindex
    用于此代理表打印正确的键
  • 如果某个键被设置为表值,则必须递归地将其替换为 在设置实际值之前,请先创建代理表

对于比这更简单的东西来说,这似乎是太多的工作和复杂化了。

您需要的是为您想要访问的每个表创建一个代理表。执行此操作的最简单方法(虽然不是最有效的方法)是在访问原始代理时返回一个新的代理表,并返回一个普通表:

mt={}
函数mt.\u索引(自、键)
打印('访问键'…键)
本地值=self.proxy[键]
如果类型(值)=“表”,则
返回setmetatable({proxy=value},mt)
其他的
返回值
结束
结束
函数mt.\uu newindex(self、key、value)
打印('设置键'…键..'到值'…到字符串(值))
self.proxy[key]=值
结束
函数setproxy(t)
new_t={proxy=t}
可设置图元(新,mt)
返回新的
结束
t={
a=1,
b=2,
c={
a=3,
b=4,
},
}
t=setproxy(t)
t、 a=2——按预期工作
t、 c.a=4——也可按预期工作

关于业绩的说明:


由于Lua中的表是垃圾收集的,因此创建新表通常被认为是“缓慢的”。但这仍然是一个观点问题;如果你写的是一个简单的手工脚本,不用麻烦优化,它仍然会非常快。如果您正在编写具有数百万次迭代的嵌套循环,或者如果您的代码需要尽可能少地在几毫秒内响应,那么您应该考虑缓存这些代理表,而不是根据您的用例 <强>。如果发现代码一次又一次地访问相同的代理表,每次都创建新的代理表,那么可以将它们缓存在代理表中,其中
proxies[table\u a]==proxy\u to\u a
,并设置一个
\u index
元方法,如果代理不存在,则创建代理。(在这一点上,折衷的办法是,由于元方法调用,新代理的创建可能会稍微慢一点)。

这是为了调试东西,所以我不介意它是否有点慢。这非常有效,谢谢!