×

Language

Close
Atelier 801
  • Forums
  • Dev Tracker
  • Log in
    • 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
  • Language
  • Forums
  • /
  • Transformice
  • /
  • Modules
  • /
  • [Tutorial] Metatables & Metamethods
[Tutorial] Metatables & Metamethods
Bolodefchoco
« Senator »
1517429100000
    • Bolodefchoco#0095
    • Profile
    • Last posts
    • Tribe
#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
    Lua code

    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
    Lua code

    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
    Lua code

    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
    Lua code

    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
    Lua code

    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
    Lua code

    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
    Lua code

    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
    Lua code

    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
    Lua code

    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
    Lua code

    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
    Lua code

    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
    Lua code

    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
« Citizen »
1517430060000
    • Mescouleur#0000
    • Profile
    • Last posts
    • Tribe
#2
  2
looks amazing
good job
King_seniru
« Censor »
1517450940000
    • King_seniru#5890
    • Profile
    • Last posts
    • Tribe
#3
  1
TY Bolo!
Wtal
« Citizen »
1517475600000
    • Wtal#5272
    • Profile
    • Last posts
    • Tribe
#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
« Senator »
1517497380000
    • Bolodefchoco#0095
    • Profile
    • Last posts
    • Tribe
#5
  1
Mouseclick1 said:
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)

Lua code

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
Lua code

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
« Censor »
1517539020000
    • King_seniru#5890
    • Profile
    • Last posts
    • Tribe
#6
  1
So why we use values form tables without adding them by integers
Bolodefchoco
« Senator »
1517540160000
    • Bolodefchoco#0095
    • Profile
    • Last posts
    • Tribe
#7
  1
Indika123 said:
So why we use values form tables without adding them by integers

Sorry, what do you mean?
Censere
« Consul »
1517617140000
    • Censere#0095
    • Profile
    • Last posts
    • Tribe
#8
  2
Nice, sort of looks like the "magic methods" of a Python class.

Last edit on 1517617200000
Bolodefchoco
« Senator »
1517619600000
    • Bolodefchoco#0095
    • Profile
    • Last posts
    • Tribe
#9
  1
Drescen said:
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

Staff Terms and Conditions of Use Privacy Policy Contact

Version 1.27