There are many more metamethods, some of them are arithmetic (e.g. addition, subtraction, multiplication), there are bitwise operations (and, or, xor, shift), comparison (<, >) and also basic type operations like == and # (equality and length). Lets build a class which supports many of these operations: a call for rational arithmetic. While this is very basic, it shows the idea.
local meta = {
-- string representation
__tostring = function(self)
return string.format("%s/%s", self.num, self.den)
end,
-- addition of two rationals
__add = function(self, rhs)
local num = self.num * rhs.den + rhs.num * self.den
local den = self.den * rhs.den
return new_rational(num, den)
end,
-- equality
__eq = function(self, rhs)
return self.num == rhs.num and self.den == rhs.den
end
}
-- a function for the creation of new rationals
function new_rational(num, den)
local self = { num = num, den = den }
setmetatable(self, meta)
return self
end
local r1 = new_rational(1, 2)
print(r1) -- 1/2
local r2 = new_rational(1, 3)
print(r1 + r2) -- 5/6
local r3 = new_rational(1, 2)
print(r1 == r3) -- true
-- this would be the behaviour if we hadn't implemented the __eq metamethod.
-- this compares the actual tables, which are different
print(rawequal(r1, r3)) -- false