×

Langue

Fermer
Atelier 801
  • Forums
  • Dev Tracker
  • Connexion
    • English Français
      Português do Brasil Español
      Türkçe Polski
      Magyar Română
      العربية Skandinavisk
      Nederlands Deutsch
      Bahasa Indonesia Русский
      中文 Filipino
      Lietuvių kalba 日本語
      Suomi עברית
      Italiano Česky
      Hrvatski Slovensky
      Български Latviešu
      Estonian
  • Langue
  • Forums
  • /
  • Transformice
  • /
  • Modules
  • /
  • [Tutorial] Metatables & Metamethods
[Tutorial] Metatables & Metamethods
Bolodefchoco
« Sénateur »
1517429100000
    • Bolodefchoco#0095
    • Profil
    • Derniers messages
    • Tribu
#1
  3

Metatables & Metamethods
http://img.atelier801.com/6424f30d.png Special thanks to Jujubitz


 In Lua, there are diferent types of metamethods. They peform some features in a table, and this same table that contains a metamethod is called a metatable.

 "This metatable is a Lua table that defines the behavior of the original value under certain special operations. You can change a number of aspects of an operation behaviour on a value by specifying fields in the metatable.", (Lua manual)

 Each metamethod is preceded by two underscores ( _ ) and the name of the event, as in __event
.

Functions Summary:
» getmetatable(table)
    - If the argument table is a metatable, this function will return all the metamethods of this table, except in the instant that a metamethod called __metatable exists; that one will be the only returned.
» setmetatable(table, metatable)
    - Sets the new metamethod(s) on the inserted table, although if the argument metatable is nil, the metamethod(s) embed on the table will be removed, and if the metamethod __metatable is on the original inserted table (if it’s not the first metamethod or the table is already a meta one), an error will be returned.
Metamethods Summary:
__index(list,index)
    - It’s triggered when an index of the table is called. The arguments are list (table) and index (name of the variable).
    Example
    Code Lua

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    garbage = setmetatable({},{
    __index = function(list,index)
    return "Not Nil! Biiiirl! The monster!!!!!"
    end
    })

    garbage.Tig = 1
    garbage.Noob = 2

    print(garbage["Tig Noob"])
    print(garbage.Tig)
    print(garbage["Noob"])
     
__newindex(list,index,value)
    - It’s triggered when an index is created inside the table. The arguments are list (table), index (name of the variable) and value (value of the new variable)
    Example
    Code Lua

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    calc = setmetatable({},{
    __newindex = function(list,index,value)
    if type(value[1]) == "number" and type(value[2]) == "number" then
    local math = {
    [1] = value[1],
    [2] = value[2],
    add = value[1] + value[2],
    sub = value[1] - value[2],
    mul = value[1] * value[2],
    div = value[1] / value[2],
    }
    rawset(list,index,math)
    else
    rawset(list,index,value)
    end
    end
    })

    calc.cake = {10,20}

    print(calc.cake[1])
    print(calc.cake[2])
    print(calc.cake.add)
    print(calc.cake.sub)
    print(calc.cake.mul)
    print(calc.cake.div)
     
__call(list,arg)
    - It’s triggered when a table is called a function. The arguments are list (table) and arg (parameter(s) passed during the calling) (can also be represented as ...)
    Example
    Code Lua

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    local call = {
    __call = function(list,arg)
    print(("[%s [%dy]] %s!"):format(arg.name,arg.age,arg.quote))
    end
    }

    humanProfile = setmetatable({},{
    __newindex = function(list,index,value)
    rawset(list,index,setmetatable(value,call))
    end
    })

    humanProfile[1] = {
    name = "Homer Simpson",
    age = 40,
    quote = "I am sorry, God, but I do not trust you!",
    }


    humanProfile[1](humanProfile[1])
     
__concat(...)
    - It’s triggered when a concatenation of different values occurs (e.g.: a table with a string). The argument is ..., which all the concatenated values are passed. (Also represented with o1, o2)
    Example
    Code Lua

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    local concat = {
    __concat = function(...)
    local values = {}
    local args = {...}
    for i = 1,#args do
    if type(args[i]) == "table" then
    for k,v in next,args[i] do
    values[#values + 1] = v
    end
    else
    values[#values + 1] = args[i]
    end
    end
    return table.concat(values,", ")
    end
    }

    list = setmetatable({},{
    concat,
    __newindex = function(list,index,value)
    if type(value) == "table" then
    rawset(list,index,setmetatable(value,concat))
    else
    rawset(list,index,value)
    end
    end
    })

    list.food = "pasta"
    list.soda = {"coke","grape"}
    list.trolls = {"Tigrounette","Pikashu"}

    print(list.soda .. list.trolls .. list.food)
     
__add(n1,n2)
    - It’s triggered when a sum occurs between non numeric (or between 1 numeric and non numeric) values. The arguments are n1 and n2, the two numbers or "values" that are being added up.
    Example
    Code Lua

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    sMath = setmetatable({},{
    __add = function(n1,n2)
    n1,n2 = (type(n1) == "table" and #n1 or n1),(type(n2) == "table" and #n2 or n2)
    return n1 + n2
    end
    })

    sMath[1] = 0
    sMath[2] = 0
    sMath[3] = 0
    sMath[4] = 0

    print(sMath + sMath + 2)
     
__sub(n1,n2)
    - It’s triggered when a subtraction occurs between non numerics (or between 1 numeric and non numeric) values. The arguments are n1 and n2, the two “numbers" or "values" that are being subtracted.
    Example
    Code Lua

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    sMath = setmetatable({},{
    __sub = function(n1,n2)
    n1,n2 = (type(n1) == "table" and #n1 or n1),(type(n2) == "table" and #n2 or n2)
    return n1 - n2
    end
    })

    sMath[1] = 0
    sMath[2] = 0
    sMath[3] = 0
    sMath[4] = 0

    print(sMath - 3)
     
__mul(n1,n2)
    - It’s triggered when a multiplication between non numeric (or between 1 numeric and non numeric) values occurs. The arguments are n1 and n2, the two "numbers" or "values" that are being multiplied.
    Example
    Code Lua

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    sMath = setmetatable({},{
    __mul = function(n1,n2)
    n1,n2 = (type(n1) == "table" and #n1 or n1),(type(n2) == "table" and #n2 or n2)
    return n1 * n2
    end
    })

    sMath[1] = 0
    sMath[2] = 0
    sMath[3] = 0
    sMath[4] = 0

    print(sMath * 4)
     
__div(n1,n2)
    - It’s triggered when a division between non numeric (or between 1 numeric and non numeric) values occurs . The arguments are n1 and n2, the two "numbers" or "values” that are being divided.
    Example
    Code Lua

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    sMath = setmetatable({},{
    __div = function(n1,n2)
    n1,n2 = (type(n1) == "table" and #n1 or n1),(type(n2) == "table" and #n2 or n2)
    return n1 / n2
    end
    })

    sMath[1] = 0
    sMath[2] = 0
    sMath[3] = 0
    sMath[4] = 0

    print(sMath / 4)
     
__pow(n1,n2)
    - It’s triggered when occurs an exponenciation (1²) between non numeric (or between 1 numeric and non numeric) values. The arguments are n1 and n2, the two "numbers" or "values" that are being exponentiated.
    Example
    Code Lua

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    sMath = setmetatable({},{
    __pow = function(n1,n2)
    n1,n2 = (type(n1) == "table" and #n1 or n1),(type(n2) == "table" and #n2 or n2)
    return n1 ^ n2
    end
    })

    sMath[1] = 0
    sMath[2] = 0
    sMath[3] = 0
    sMath[4] = 0

    print(sMath ^ 2)
     
__mod(n1,n2)
    - It’s triggered when a mod (1%2 (Gets the rest of division between two numbers)) occurs between non numeric numbers (or 1 numeric and non numerics). The arguments are n1 and n2, the two "number" or "values" that are being "moduled".
    Example
    Code Lua

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    sMath = setmetatable({},{
    __mod = function(n1,n2)
    n1,n2 = (type(n1) == "table" and #n1 or n1),(type(n2) == "table" and #n2 or n2)
    return n1 % n2
    end
    })

    sMath[1] = 0
    sMath[2] = 0
    sMath[3] = 0
    sMath[4] = 0

    print(sMath % 3)
     
__unm(n1)
    - It’s triggered when a non numeric value is called unary (in this case, it’s the same as setting it "-var" in order to make the var number a negative one). The argument is n1, the "number" or "value” that is being turned into a negative number.
    Example
    Code Lua

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    sMath = setmetatable({},{
    __unm = function(n1)
    n1 = (type(n1) == "table" and #n1 or n1)
    return -n1
    end
    })

    sMath[1] = 0
    sMath[2] = 0
    sMath[3] = 0
    sMath[4] = 0

    print(-sMath)
     
__metatable()
    - Blocks the function getmetatable from collecting the real metamethods from the inserted table and, instead of it, ends up returning the metamethod __metatable as a way of protection.
    Example
    Code Lua

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    str = setmetatable({},{
    __metatable = "Nothing here, noob!",
    __newindex = function(list,key,value)
    print(key .. " Biirl!")
    rawset(list,key,value)
    end
    })

    print(getmetatable(str))
    print(getmetatable(str).__newindex)

    str.test = '?'

    tbl = setmetatable({},{
    __newindex = function(list,key,value)
    print(key .. " Huuuu!")
    rawset(list,key,value)
    end
    })

    print(getmetatable(tbl))
    print(getmetatable(tbl).__newindex)

    tbl.test = '?'
     
Mescouleur
« Citoyen »
1517430060000
    • Mescouleur#0000
    • Profil
    • Derniers messages
#2
  2
looks amazing
good job
King_seniru
« Censeur »
1517450940000
    • King_seniru#5890
    • Profil
    • Derniers messages
    • Tribu
#3
  1
TY Bolo!
Wtal
« Citoyen »
1517475600000
    • Wtal#5272
    • Profil
    • Derniers messages
    • Tribu
#4
  1
But why we use them. It would be better if i ask that if i didnt use metatables do it throw any error. If yes give an example pls. TY
And Nice thread!
Bolodefchoco
« Sénateur »
1517497380000
    • Bolodefchoco#0095
    • Profil
    • Derniers messages
    • Tribu
#5
  1
Mouseclick1 a dit :
But why we use them. It would be better if i ask that if i didnt use metatables do it throw any error. If yes give an example pls. TY
And Nice thread!

Well. Try this code (sum a table to 100)

Code Lua

1
2
3
4
a = {10, 20, 30, 40, 70}

print(a + 100)
--input:3: attempt to perform arithmetic on a table value (global 'a')

Now, let's use a metatable in " a " that returns the first value of the table when we try to sum it to something
Code Lua

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
a = {10, 20, 30, 40, 70}

a = setmetatable(a, {
__add = function(obj1, obj2)
if type(obj1) == "table" then
-- First value if is number or the value 1
obj1 = tonumber(obj1[1]) or 1
end
if type(obj2) == "table" then
-- First value if is number or the value 1
obj2= tonumber(obj2[1]) or 1
end

return obj1 + obj2
end
})

print(a + 100)
print(a + {20,30})
-- 110 (a[1] + 100)
-- 30 (a[1] + 20), 20 because ({20, 30})[1] = 20
King_seniru
« Censeur »
1517539020000
    • King_seniru#5890
    • Profil
    • Derniers messages
    • Tribu
#6
  1
So why we use values form tables without adding them by integers
Bolodefchoco
« Sénateur »
1517540160000
    • Bolodefchoco#0095
    • Profil
    • Derniers messages
    • Tribu
#7
  1
Indika123 a dit :
So why we use values form tables without adding them by integers

Sorry, what do you mean?
Censere
« Consul »
1517617140000
    • Censere#0095
    • Profil
    • Derniers messages
    • Tribu
#8
  2
Nice, sort of looks like the "magic methods" of a Python class.

Dernière modification le 1517617200000
Bolodefchoco
« Sénateur »
1517619600000
    • Bolodefchoco#0095
    • Profil
    • Derniers messages
    • Tribu
#9
  1
Drescen a dit :
Nice, sort of looks like the "magic methods" of a Python class.

Kinda xD It's metaprogramming
  • Forums
  • /
  • Transformice
  • /
  • Modules
  • /
  • [Tutorial] Metatables & Metamethods
© Atelier801 2018

Equipe Conditions Générales d'Utilisation Politique de Confidentialité Contact

Version 1.27