Question about metatables

Basically, I’m trying to use __newindex, so whenever I try to set a table value that doesn’t exist the __newindex activates and inserts it automatically. But when I try to do table.insert it does an error, but if I do table.insert in a function and run that it works. So I just want to know the reasoning why

why can I do this:

 local myTable = {30,20,10,5}
 local function tableInsert(index, value)
      table.insert(myTable,index,value)
 end

  setmetatable(myTable, {


__index = function(table,index)
	--print("no data how sad")
	--return(1)
end;


__newindex = function(table,index,value)
	tableInsert(index, value)
end


})
print(myTable[5])
wait(1)
myTable[5] = "hey!"
print((myTable[5]))

SDA
But not this:

    local myTable = {30,20,10,5}

    setmetatable(myTable, {


__index = function(table,index)
	--print("no data how sad")
	--return(1)
end;


__newindex = function(table,index,value)
	table.insert(myTable,index,value)
end


})

print(myTable[5])
wait(1)
myTable[5] = "hey!"
print((myTable[5]))

asdrewq

1 Like

The problem is pretty simple, since table itself is a global variable and you’re using it as a local parameter inside the scope of the function attached to the __newindex metamethod it changes the table global with functions inside with the myTable table inside that function. You can fix this by changing the parameter named “table” with something else.

Here is how it works in a more detailed matter:

local myTable = {30,20,10,5}

local function tableInsert(index, value)
	--Here "table" variable is still the standart normal one so you can use "table.insert" function here.
	print(table) --Outputs the hexadecimal memory address the original global table is stored since this scope is not affected. This is the 5th thing that is outputted on console.
	table.insert(myTable,index,value) --This naturally works since the variable "table" is not redefined in this scope.
end

setmetatable(myTable, {
	__newindex = function(table,index,value)
		--Here the first parameter is named "table", the same one as the global variable "table", 
        --so inside this function the parameter overrides the global "table" variable with the table 
		--that fired the metamethod which is the "myTable" table. Which prevents you from calling the 
        --"table.insert" function since it no longer references to original global table.
		
		--Keep in mind that this change only applies inside this function scope, it stays original for everywhere else.
		print(table) --Outputs the hexadecimal memory address of the "table" and as you can see it outputs the same address as "print(myTable)". This is the 4th thing that is outputted on console.
		tableInsert(index, value) --Calls the "tableInsert" function.
		print(table[5]) --Outputs "hey!". This is the 6th thing that is outputted on console.
	end
})
print(table) --Outputs the hexadecimal memory address the original global table is stored. This is the 1st thing that is outputted on console.
print(myTable) --Outputs the hexadecimal memory address the "myTable" table is stored. This is the 2nd thing that is outputted on console.
print(myTable[5]) --Outputs "nil" since there is no value attached to it and I got rid of the __index metamethod for this example. This is the 3rd thing that is outputted on console.
myTable[5] = "hey!" --Calls the function attached to __newindex metamethod.
print(myTable[5])  --Outputs "hey!". This is the 7th and final thing that is outputted on console.

--Output
->table: 0x2b4f70a0d2242454 --Line 16 "print(table)"
->table: 0xe7dd8a3d9aabf2a4 --Line 17 "print(myTable)"
->nil --Line 18 "print(myTable[5])"
->table: 0xe7dd8a3d9aabf2a4 --Line 11 "print(table)"
->table: 0x2b4f70a0d2242454 --Line 5 "print(table)"
->hey!(x2) --Line 13 "print(table[5])" then Line 20 "print(myTable[5])"
1 Like