As a Roblox developer, it is currently too tedious to detect changes in a table. Currently, the only ways to detect changes in a table are these two methods.
First Method:
This method will have issues if you have things already defined in the original table since __newindex only triggers if the Value in the original table doesn’t exist.
local Sample, Changed = {}, Instance.new("BindableEvent")
local Table = setmetatable({}, {
__index = Sample,
__newindex = function(self, Key, Value)
if Sample[Key] ~= Value then
local OldValue = Sample[Key]
Sample[Key] = Value
Changed:Fire(Key, Value, OldValue)
end
end,
})
Changed.Event:Connect(function(Key, Value, OldValue)
print(Key, Value, OldValue)
end)
Table.Name = "focasds"
Table.Name = "Make This A Thing"
Second Method:
local Table, Changed = {}, Instance.new("BindableEvent")
local function SetValue(Key, Value)
if Table[Key] ~= Value then
local OldValue = Table[Key]
Table[Key] = Value
Changed:Fire(Key, Value, OldValue)
end
end
Changed.Event:Connect(function(Key, Value, OldValue)
print(Key, Value, OldValue)
end)
SetValue("Name", "focasds")
SetValue("Name", "Make This A Thing")
Issue: There many occasions where we need to detect changes in a table to update other things that rely on a table, for example:
- I have a custom object that has an Enabled property, when this one changes some code needs to run to make other changes. To avoid both methods mentioned, I am forced to just add a function named SetEnabled since is easier than all of that code, but I love following the style that the engine provides. (‘Enabled’ property for particles, ScreenGui, constraints, scripts, etc…)
- I have a huge table with some info in it, this one can get changed at any time but there is no way to detect changes either unless I execute one of the two ways mentioned.
- The methods mentioned in my opinion uses a bit more memory and kinda slow down things as well. (This third point is minimal and is not a big issue)
Proposed Solution:
First Solution: (My favorite)
A table.changed function which requires a Table and a Callback. When something gets added, changed, or removed from the Table the Callback should be called and pass the Key, Value, and the Previous Value before the change.
The function should be called no matter how things are changed in the table. In other words, changing normally, using rawset, and even things removed by the GC cycle in weak metatables should not affect table.changed.
local Table = {}
table.changed(Table, function(Key, Value, OldValue)
print(Key, Value, OldValue)
end)
Second Solution:
A __changed metamethod which gets called when something gets added, changed, or removed from the Table the function in it should be called and pass the Key, Value, and the Previous Value before the change.
The function should be called no matter how things are changed in the table. In other words, changing normally, using rawset, and even things removed by the GC cycle in weak metatables should not affect the behavior of __changed.
local Table = setmetatable({}, {
__changed = function(self, Key, Value, OldValue)
print(Key, Value, OldValue)
end,
})
If Roblox is able to address this issue, it would improve my development experience because I will be able to detect changes efficiently, write less code, it will help beginners, there will not be any need to use the two methods mentioned at the beginning of the post, and finally I will be able to detect changes in any table without being affected by rawset, already existing keys, and gc cycle.
Thank you.