How to understand metatable in Lua?
Asked Answered
M

2

5

I have used Python, but now I'm learning Lua because of Torch. The word 'metatable' is really hard to understand for me. For example, is metatable a special kind of table? How does it change the behavior of table?

Muscovite answered 6/6, 2016 at 9:18 Comment(2)
See lua.org/pil/13.html.Centralization
Especially see §13.4 because __index is used in object-oriented Lua.Devilfish
O
13

A metatable is simply a table that is used to control the behavior of another table (or userdata, or other Lua value). A table is a metatable only because it is used as a metatable. That is, being a "metatable" is not a fundamental property of a table. There is no "create_metatable" function or anything. It's just the name we use for a table which is used to control other tables.

Certain operations on tables (or userdata) are specified to check the table's metatable first. If the table (or userdata) has a metatable, and that metatable has a certain key/value pair in it, then the operation will use that key/value pair to perform that operation instead of the normal logic.

Each operation which can be overridden by a metatable has a specific key name associated with it. So if you try to perform addition on a table, the system will look for the __add key in the metatable in order to access it.

The value in the pair is usually (though not always) a function. Such functions are generally called "metafunctions". The parameters it takes and the meaning of its return value is defined by the particular operation calling it. A few operations allow the value to be a table or something else.

In Lua, you assign a metatable to a table (but not userdata) with the setmetatable function. From C, you use the lua_setmetatable function to assign a table (or userdata) a metatable.

Metatables are particularly important for C code that exposes C objects as userdata. Raw userdata is just an opaque blob of bits; Lua defines very few legal operations that can be performed on them by default. But by assigning them a metatable, you can give the userdata more abilities through metafunctions.

Note that Lua values other than tables and userdata can have metatables. However, unlike tables and userdata, values of each Lua type all share the same metatable for that type. So all strings have the same metatable, all numbers have the same metatable, etc.

Ovenbird answered 6/6, 2016 at 14:2 Comment(0)
H
0

Hello

After a while of reading and understanding what a metatable could be i like to post a working example. So everybody can see and feel how usefull it can be. The example change the # operator for the associated table. Because i realized # counts only correct not named keys. # ignores also 0 and negative numbers. And here is the working example how to replace it with a function that counts every table correct...

 # lua
Lua 5.3.5  Copyright (C) 1994-2018 Lua.org, PUC-Rio
> -- Defining a table with 3 key/value pairs
> my_table={[0]=0,[1]=1,['metatable']={}}
> #my_table
1
> -- # is counting wrong it counts only my_table[1]
> -- Now set the empty my_table.metatable to my_table
> setmetatable(my_table,my_table.metatable)
> -- So it can be accessed without getmetatable()
> -- Now replacing # for associated table my_table
> -- in my_table.metatable with the metafuncion __len
> my_table.metatable.__len=function(array) local incr=0 for _ in pairs(array) do incr=incr+1 end return incr end
> -- Let's test # ...
> #my_table
3
> -- Now # is usefull because it counts correct
> -- And my_table.metatable can be set as a metatable for other tables
> -- where # is counting wrong but needed to count the correct way
> #_G
0
> setmetatable(_G,my_table.metatable)
> #_G
45
> #package.loaded
0
> setmetatable(package.loaded,my_table.metatable)
> #package.loaded
12
> -- Like _G or package.loaded for example
Headliner answered 15/7, 2020 at 8:33 Comment(2)
"Because i realized # counts only correct not named keys." That's because it's not supposed to. It determines the length of the array part of a table (the sequence of integer keys increasing monotonically from 1 to the first nil entry). That's its job.Ovenbird
Yes i agree and if you know that then the behavior is clear. But "the length of the array part" is in this case not the length of the associated array part.Headliner

© 2022 - 2024 — McMap. All rights reserved.