Scripting Helpers is winding down operations and is now read-only. More info→
← Blog Home

Metatables? A table within a table? Maybe not

Countless times have I seen a metatable incorrectly described. There was a user on the ROBLOX Scripting Helpers forum who put it simply:

A metatable is a table inside of another table

Oh? I guess that makes them easy enough. I'll write a metatable out real quick.

local t = { m = {} }

Awesome. We have a metatable. Done. Blog post over.

Not so much. In fact, I'm not even sure where that definition arose - or how. You might be able to conceptualize it as a table within another - but that is extremely far fetched.

So, in simple terms, what is a metatable? I like to tell people it is what holds the settings for another table. How the table the metatable is linked to should act under certain conditions. It is by no means just a table inside of another.

How can you make one? You actually make two tables, and then set one as a metatable to the other. Like so:

local t1 = {}
local t2 = {}
setmetatable(t1, t2)

Can you guess which table is now the metatable of the other? It goes in reverse order. Read it as "t2 is now the metatable of t1."

If you haven't learned about tables, then it is discourage for you to continue reading.

So what can you do with a metatable? There are many values you can set as indexes which serve as metamethods. These are the "settings" you can attach to a table. An example of using one of the metamethods (__index).

local t1 = {}
local t2 = {
    __newindex = function(tab, i, v)
        print(tab,i,v)
        -- tab is the table (t1) being changed
        -- i is the index being set
        -- v is the value being assigned to that index
    end
}
setmetatable(t1, t2)

t1[1] = 5
print(t1[1])

It's important to note that 5 was never set to t1's first index. The metatable overrides the operation. You can choose to continue on with the setting of a new index inside the __newindex metamethod. How could you do this? Some of you might think that trying to set the index of t1 to a value inside the __newindex function might just cause an infinite loop, because the metamethod would catch itself. Over and over.

Well, you'd be right. We have to use the rawset function. This function will set an index of a table without invoking our metamethod.

local t1 = {}
local t2 = {
    __newindex = function(tab, i, v)
        print(tab,i,v)
        -- tab is the table (t1) being changed
        -- i is the index being set
        -- v is the value being assigned to that index

        rawset(tab, i, v) -- set the index of tab[i] to v
    end
}

setmetatable(t1, t2)

t1[1] = 5
print(t1[1])

Notice the that rawset is now in the __newindex function. If you were to run the previous code example, you would have gotten nil on the last print line. Using the second code example, you will get "5" - exactly what we set it to.

Some of you might wonder what exactly you can use metatables for. It might seem like a useless Lua feature to some of you, and maybe a gold mine to others. Creativity is a broad concept, and gives birth to even broader ideas. There are many examples of what others have done with metatables - try looking around. There might even be one or two things in ROBLOX, sitting right in front of you, that use metatables.

Posted in Scripting Tips

Commentary

Leave a Comment

Hippalectryon says: February 25, 2014
Thank you Stephan :D. At least, someone does a good and short briefing about that subject
adark says: February 26, 2014
The literal definition of metatables is "Tables *about* Tables." Meta is content that describes identical content. Tables about tables. For another example, 'swag' is meta in that swag is actually stuff like band t -shirts or other merchandising, whereas 'swag' t-shirts and such is swag about the concept of swag (Tbh, a somewhat bastardized concept of it, but w/e)! Metaswag!
lah30303 says: December 3, 2014
Yea, I remember when I was learning metatables years ago that old definition confused the heck out of me.
OMEGA27304 says: December 25, 2015
Meta tables is basically for Object Oriented Programming. It basically works like a class.
FiredDusk says: March 28, 2017
AYEEE