Checking when an element in a dictionary has been changed?

I’m currently trying to figure out how to know when an element in a dictionary has been changed for some data management. The first thing I thought was using metatables in order do achieve that. I attempted to accomplish that with __index and __newindex , but it didn’t really work (it worked, but not when a key’s value changes)

Attempt with __newindex:

local simpleTab = {
breakfast = "cereals",
dinner = "pasta",
dessert = "cake"
}
local metaTab = {__newindex = function(object,key) 
print("omg the table has been indexed. that's what I want for now!")
end}
setmetatable(simpleTab,metaTab)
simpleTab.dinner = "none"

I also tried with __index, but yeah,… anyways, for make it short, whether I change breakfast, dinner or dessert, I’d like to know that these values changed. Note that this is just a mere example with ridiculous meals time.

1 Like

You’ll need a dummy dictionary since __index and __newindex only register when there’s nothing already at that index. For example:

local secretDict = {
	breakfast = "cake",
	dinner = "cake",
	dessert = "cake",
}

local mainDict = {}
local metaTable = {}
metaTable.__newindex = function(table, key, value)
	if secretDict[key] then
		-- they tried to change an existing value
	else
		-- it's a completely new value
		secretDict[key] = value
	end
end

metaTable.__index = function(table, key)
	return secretDict[key]
end

setmetatable(mainDict, metaTable)
print(rawget(mainDict, "breakfast"), mainDict.breakfast) --> nil and "cake"
mainDict.breakfast = "some actual breakfast food instead of cake"
print(rawget(mainDict, "breakfast"), mainDict.breakfast) --> still nil and "cake"

rawget is just to get what’s actually in the table while ignoring metatables. You can use rawset to ignore metatables and set a value as well. There’s no way to make the actual table edit-proof, so your best bet is something like this.

7 Likes