Is there a way to detect change in a table

I want to detect change in a table (like when something is added or changed)

supaTable = {
	ToiletFlushed = false
	Poop = {}
}
supaTable.ToiletFlushed = true

I don’t know how

If you do please let me know Thanks

2 Likes

MAJOR UPDATE (2021-04-07)


There is no built-in event such as .Changed(), which can be used with instances, and for a good reason - it isn’t necessary. Code block that modifies a particular table can as well be the one that “notifies” about changes: in other words, the function that changes a particular table is also the one that calls other functions which need to run when table is modified.

It’s the most efficient way! What I’m talking about is visible in the following example:

local mainTable = {"Adopt me", "Jailbreak", "Phantom Forces"}

local function onGameAdded()
	print("Game was added to our list!")
end
local function addGameToTable(gameToAdd)
	table.insert(mainTable, gameToAdd)
	onGameAdded()
end

No need to listen to any changes.

However, we still indeed have a relatively efficient way to detect changes, although we should preferably choose manual notifying in terms of performance and simplicity.


METATABLES

There are two metamethods that come in handy, although they are not activated when table.insert() and table.remove() are used. They only respond to manual indexing.

Another important fact to mention is that metamethods 1 __index only fires when we index and empty element 2 __newindex only fires when a new element is added to the table.

__index(table, key): “Fires when table[index] is indexed, if table[index] is nil. Can also be set to a table, in which case that table will be indexed.”

__newindex(table, key, value): “Fires when table[index] tries to be set (table[index] = value), if table[index] is nil. Can also be set to a table, in which case that table will be indexed.”

(Metatables | Roblox Creator Documentation, Roblox Dev Hub, 2021-04-07, read more about metatables here)

If they only respond to empty indexes, how are we going to detect changes to existing ones?

Firstly, I should mention that this is not my solution. In fact, it can be found in original lua reference manual, 13.4.4 - Tracking table accesses.

We create an empty table. Instead of adding elements to it, __index and __newindex only return new values, but do not let the table be updated - instead, they update a separate so called proxy table that is present in the background, leaving the original one unchanged. Empty table can, again, detect changes!

--[[
	We will be indexing surfaceTable the whole time,
	which will stay empty.
]]
local surfaceTable = {}
--[[
	Proxy table is going to be hidden, but will actually reflect
	all the changes. This table will be updated each time.
]]
local _mainTable = {}

setmetatable(surfaceTable, {
	__index = function(self,key)
		print("Key number ".. key .." was accessed.")
		return _mainTable[key] -- We return the key from proxy table.
	end,
	
	__newindex = function(self,key,value)
		print("Key number ".. key .. " was updated. New value: ".. (value or "nil"))
		_mainTable[key] = value -- Now we update our proxy table.
	end,
})

Example of use:

-- Dictionaries:
surfaceTable["a"] = 15 --> detects new key and new value

surfaceTable["a"] = nil --> removes and detects removal of "a"

What about tables? How can I repace table.insert()?

local tab = {}
table.insert(tab, "element")
-- Equivalent operation:
tab[#tab+1] = "element"

And what about table.remove()?

local tab = {"element"}
table.remove(tab, 1)
-- Equivalent operation:
tab[1] = nil

table.find()?

Instead of searching in original table, we have to “inspect” the proxy table. Same loop logic, but not to be performed on emtpy surface table.

Follow this article if you’re the boss and are going to learn about metatables :sunglasses: :

@sir_vitamin and @BlueMinionIW

23 Likes

What is the scripf? Paste ut so I can understand.