Scripting HelpersARCHIVE
A little piece of Roblox history. Preserved for everyone, one question at a time.Read about the archive →
COMMUNITY QUESTION

How would one go about locking a table?

Apologies if the title doesn't make entire sense, though I was just curious if it was possible to prevent any extra additions or changes to a table, let's say I did something like this:

local table1 = {
   "Hello", "Hi"
};

I have my table with two Elements present, I'd set these and somehow locked the table so they're permanent, unamendable, and nothing new can be implemented. Like so:

table1[1] = "Cya"; table1[2] = "Goodbye"
table1[3] = --// Some random Element.

Basically, the end-goal I have is to reject all of the above, I'd assume it would require metamethods to do such a thing, or maybe I'm wrong? How would I go about doing this?

1 comment

0

i'm writing an answer for u

2 answers

Well yes, and no, it is possible with the use of the _newindex metamethod.


__NewIndex


The __newindex metamethod fires when a index not already in a table by the time a metatable containing the __newindex metamethod is set to some number, for example:

local tbl = {1,2,3}
setmetatable(tbl,{__newindex = ...})

tbl[4] = 5--fires the metamethod
tbl[3] = 5--doesnt fire the metamethod

This can be used to do the following:

local tbl = {1,2,3}
setmetatable(tbl,{__newindex = function() print("ree no access")end})

tbl[4] = 5--ree no access
tbl[3] = 5
print(tbl[4],tbl[3])--nil,5

this would not set the 4th index of array tbl to a number, but rather keep it at its current value, which is nil.

Therein also lies the caveat of this method, being that it doesnt lock indexes already in the table, meaning that the script can still modify preexisting indexes.

Hopefully this helped, sorry I wasn't able to give a complete answer to your question

1 comment

0

I should've mentioned, I already had an attempt involving __newindex, but this does clean up some things , this will help me make it more efficient. I've upvoted this, and may accept it if not other ways are provided, thanks for the help anyway!

#__newindex

This metamethod is invoked upon t.k = v or t[k] = v.

This isn't invoked for existing table fields which is good in this case.

local x = {}
local m = {__newindex = function(t, k, v)
    -- t is the table that m is the metatable of, k is the key, v is the value
    t[k] = nil
end}

setmetatable(x, m)

x.foo = "bar"
print(x.foo)

So this just instantly sets the field to nil.

There is still a problem.

These codes will result in a stack overflow! Line 4 is invoking __newindex again and that invokes the function which is invoking it again and it's a circle. So we must use the rawset function. All it does is not invoke __newindex.

local x = {}
local m = {__newindex = function(t, k, v)
    -- t is the table that m is the metatable of, k is the key, v is the value
    rawset(t, k, nil) -- (t, k, v) in this case were setting to nil 
end}

setmetatable(x, m)

x.foo = "bar"
print(x.foo)

In addition

If you want to lock your tables metatable youcan use the __metatable metamethod.

local m = {
    __metatable = "Metatable locked"
}

local x = {}
setmetatable(x, m)
print(getmetatable(x)) --> Metatable locked

6 comments

0

I understand newindex from the help of both your answers, though could you exlaborate on __metatable?

0

__metatable is invoked when you try getting/setting the metatable of x

0

@feahren, a__metatable fires when you try and get/set the metatable of a table, and the getmetatable function will then return the corresponding value of the __metatable key

0

read this for a better explanation lol http://lua-users.org/wiki/MetatableEvents

0

Hm, yes but how does this lock it?

0

It prints "Metatable locked" when I tried getting the metatable. So yes

This discussion is preserved as it was. New answers, comments, and votes are closed.