How would I check if a value has been inserted or removed from a table?

Similarly to Value.Changed(), I’ve been wondering if there’s something for Tables? I did try setting a metatable, however the function won’t run if something has been inserted or removed.

2 Likes

You can check every frame or you can use metatables.

EDIT: I made this a while ago but this is a way to do it with metatables.

local Class = {}

function Class:__index(key)
    
    return rawget(self, "proxy")[key]
    
end

function Class:__newindex(key, value)
    
    local proxy = rawget(self, "proxy")
    
    proxy[key] = value
    
    if key == "Property" then
        
        print("Property was changed to: "..value)
        
    end
    
end

function Class.new()
    
    local self = setmetatable({}, Class)
    
    local proxy = {}
    
    function proxy:Method()
        
        print("Hello world!")
        
    end
    
    rawset(self, "proxy", proxy)
    
    return self
    
end

local obj = Class.new()

obj.Property = 20

obj:Method()
1 Like

Metatables don’t get fired by table.insert and table.remove.
You have to add values manually.

function table.insert(t, v)
  t[#t+1] = v
end

function table.remove(t, k)
  t[k]=nil; --> Indexes don't get shifted, have that in mind.
end
local t = {}
setmetatable(t, {
  __newindex = function(self, k, v)
    if v then
      print('new value', k)
    else
      print('value removed', k)
    end
  end
})
3 Likes

Oh, thanks for the fast reply, that solved my problem @Quaration, @Legoracer

1 Like

While I think @Legoracer solution works, it’s lacking in the sense that it’s overriding the default table insert and removing behavior, which is generally not desired as you lose the ability to insert or remove at any position. A better way is to have the overridden function callback the original function and check for any event handler in the table and if present call it. Metatables are fancy, but are not always the solution.

local insert = table.insert
local remove = table.remove

function table.remove(...)
	local params = {...}
	local t = params[1]
	if t["OnRemove"] then
		if t.OnRemove(...) then
			remove(...)
		end
	end
end

function table.insert(...)
	local params = {...}
	local t = params[1]
	if t["OnInsert"] then
		if t.OnInsert(...) then
			insert(...)
		end
	end
end

t = {
	1, 2, 3, 4, 5, 6, 7,
	OnRemove = function(self, pos)
		print(self, pos)
		return true
	end,
	OnInsert = function(self, vp, value)
		print(self, vp, value)
		return true
	end
}

table.remove(t, 2)
print(table.concat(t, ", "))
table.remove(t, 3)
print(table.concat(t, ", "))
table.insert(t, "end")
print(table.concat(t, ", "))
table.insert(t, 1, "start")
print(table.concat(t, ", "))

With this implementation you must return true to allow the inserting or removing in the event handler, you can return false to block the insertion or removal, say you only want numbers to be added.

2 Likes

Hey, @Destrings. I see what you mean, I’ve bumped into another problem which prevents me from modifying a table. " [ Attempt to modify a readonly table] " Not sure what’s the issue here

Right, in ROBLOX, due to security reasons, you can’t modify the “table” table. So you can’t override the functions. You will have to rename them as so

function remove(...)
	local params = {...}
	local t = params[1]
	if t["OnRemove"] then
		if t.OnRemove(...) then
			table.remove(...)
		end
	end
end

function insert(...)
	local params = {...}
	local t = params[1]
	if t["OnInsert"] then
		if t.OnInsert(...) then
			table.insert(...)
		end
	end
end

t = {
	1, 2, 3, 4, 5, 6, 7,
	OnRemove = function(self, pos)
		print(self, pos)
		return true
	end,
	OnInsert = function(self, vp, value)
		print(self, vp, value)
		return true
	end
}

remove(t, 2)
print(table.concat(t, ", "))
remove(t, 3)
print(table.concat(t, ", "))
insert(t, "end")
print(table.concat(t, ", "))
insert(t, 1, "start")
print(table.concat(t, ", "))
7 Likes

You could use setfenv() on any functions that need to do any inserting or removing, but please nobody ever do that - it would most definitely be bad practice!

(or if you’re really hardcore and/or love terrible ideas, sandbox everything in your game)

1 Like