Metamétodos aritméticos
Sobrecarregue +, -, *, / e outros operadores com metamétodos.
Metamétodos aritméticos é uma aula grátis de Lua Academy no CoddyKit. Esta é a aula 3 de 4. Você pode ler a aula completa abaixo gratuitamente — depois pratica ao vivo no navegador com um editor de código integrado e um tutor de IA 24/7. Faz parte do caminho de aprendizado de Lua Academy, e seu progresso é sincronizado entre a web e o app CoddyKit. O curso de Lua Academy inclui 4 aulas no total.
Nomes dos Metamétodos
O Lua define metamétodos para todos os operadores aritméticos. Quando o Lua encontra uma operação aritmética em uma tabela, ele procura o metamétodo correspondente na metatabela da tabela. Se ambos os operandos forem tabelas, o Lua verifica primeiro a metatabela do operando esquerdo.
-- Operator -> Metamethod
-- a + b -> __add
-- a - b -> __sub
-- a * b -> __mul
-- a / b -> __div
-- a % b -> __mod
-- a ^ b -> __pow
-- a // b -> __idiv
-- -a -> __unm (unary minus)
-- #a -> __len
print("Metamethods defined for all Lua operators")__add para Adição de Vetores
Defina __add em uma tabela de vetor para permitir o uso de +. O metamétodo recebe dois operandos e retorna um novo valor. Ambos os operandos podem ser tabelas, ou um deles pode ser um número — seu metamétodo deve lidar com os dois casos.
local Vec = {}
Vec.__index = Vec
Vec.__add = function(a, b)
return setmetatable({x=a.x+b.x, y=a.y+b.y}, Vec)
end
Vec.__tostring = function(v)
return string.format("Vec(%g,%g)", v.x, v.y)
end
function Vec.new(x,y) return setmetatable({x=x,y=y},Vec) end
local v1 = Vec.new(1,2)
local v2 = Vec.new(3,4)
print(tostring(v1 + v2)) -- Vec(4,6)__sub __mul __div
Defina __sub, __mul e __div de modo semelhante. Para a multiplicação, trate os casos tabela*tabela e tabela*número verificando os tipos dos operandos dentro do metamétodo.
local Vec = {}
Vec.__index = Vec
local function V(x,y) return setmetatable({x=x,y=y},Vec) end
Vec.__sub = function(a,b) return V(a.x-b.x, a.y-b.y) end
Vec.__mul = function(a,b)
if type(a)=="number" then return V(a*b.x, a*b.y)
elseif type(b)=="number" then return V(a.x*b, a.y*b)
else return a.x*b.x + a.y*b.y -- dot product
end
end
Vec.__tostring=function(v) return "("..v.x..","..v.y..")" end
local v = V(3,4)
print(tostring(v * 2)) -- (6,8)
print(tostring(V(1,0) - V(0,1))) -- (1,-1)__unm: Menos Unário
__unm é o metamétodo do menos unário, invocado quando o Lua avalia -obj. Ele recebe o operando (o mesmo valor é passado duas vezes por consistência) e retorna o valor negado.
local Vec = {}
Vec.__index = Vec
local function V(x,y) return setmetatable({x=x,y=y},Vec) end
Vec.__unm = function(a) return V(-a.x, -a.y) end
Vec.__tostring = function(v)
return string.format("(%g,%g)", v.x, v.y)
end
local v = V(3, -4)
print(tostring(-v)) -- (-3,4)
print(tostring(-(-v))) -- (3,-4)__len para Comprimento Personalizado
__len é chamado quando #obj é avaliado em uma tabela sem uma sequência inteira bruta. Defina-o para retornar um “comprimento” significativo para tipos personalizados, como conjuntos, filas ou contêineres ponderados.
local Bag = {}
Bag.__index = Bag
Bag.__len = function(b) return b._count end
function Bag.new()
return setmetatable({_count=0, _items={}}, Bag)
end
function Bag:add(item, qty)
self._items[item] = (self._items[item] or 0) + (qty or 1)
self._count = self._count + (qty or 1)
end
local bag = Bag.new()
bag:add("apple", 3)
bag:add("banana", 2)
print(#bag) -- 5__mod e __pow
__mod trata do operador %; __pow trata de ^. Eles são menos comuns, mas úteis para tipos numéricos personalizados, como inteiros grandes, frações ou objetos de aritmética modular.
local Modular = {}
Modular.__index = Modular
local M = 1000000007
local function mod(n)
return setmetatable({n = n % M}, Modular)
end
Modular.__add = function(a,b) return mod(a.n + b.n) end
Modular.__mul = function(a,b) return mod(a.n * b.n) end
Modular.__pow = function(a,b)
local r, base, exp = mod(1), a, b
while exp > 0 do
if exp%2==1 then r = r*base end
base = base*base; exp = math.floor(exp/2)
end
return r
end
print((mod(2) ^ 30).n) -- 73741817 (2^30 mod 1e9+7)__concat
__concat é acionado pelo operador .. quando pelo menos um operando tem esse metamétodo. Isso permite definir concatenação para tipos personalizados ou criar DSLs encadeáveis.
local Builder = {}
Builder.__index = Builder
Builder.__concat = function(a, b)
local result = {}
for _, v in ipairs(a._parts) do result[#result+1] = v end
if type(b) == "string" then result[#result+1] = b
else for _, v in ipairs(b._parts) do result[#result+1] = v end end
return setmetatable({_parts=result}, Builder)
end
Builder.build = function(b) return table.concat(b._parts) end
local function S(s) return setmetatable({_parts={s}},Builder) end
print((S("Hello") .. ", " .. S("World") .. "!"):build())Metamétodos de Comparação
__eq define == para tabelas (chamado somente quando ambos os operandos têm a mesma metatabela). __lt define <; __le define <=. Observação: ~= usa __eq; > usa __lt com os argumentos invertidos; >= usa __le.
local Vec = {}
Vec.__index = Vec
local function V(x,y) return setmetatable({x=x,y=y},Vec) end
Vec.__eq = function(a,b) return a.x==b.x and a.y==b.y end
Vec.__lt = function(a,b)
return (a.x^2+a.y^2) < (b.x^2+b.y^2) -- by magnitude
end
print(V(1,2) == V(1,2)) -- true
print(V(1,2) == V(1,3)) -- false
print(V(1,0) < V(2,0)) -- true (1 < 2)Encadeando Metamétodos
Como os metamétodos retornam valores (geralmente novas tabelas), as operações podem ser encadeadas naturalmente. Cada operador retorna um novo objeto, e o operador seguinte usa esse resultado. Isso permite expressões aritméticas encadeáveis em tipos personalizados.
local Vec = {}
Vec.__index = Vec
local function V(x,y) return setmetatable({x=x,y=y},Vec) end
Vec.__add = function(a,b) return V(a.x+b.x,a.y+b.y) end
Vec.__mul = function(a,b)
if type(b)=="number" then return V(a.x*b,a.y*b) end
return V(a.x*b.x+a.y*b.y, 0) -- simplified
end
Vec.__tostring=function(v) return "("..v.x..","..v.y..")" end
local result = V(1,0) + V(0,1) * 3
print(tostring(result)) -- (1,3)Operações com Tipos Mistos
Quando você escreve vec * 2, o operando esquerdo é a tabela. Quando escreve 2 * vec, o operando esquerdo é um número (sem metamétodo), então o Lua verifica a metatabela do operando direito em busca de __mul. Trate as duas ordens no seu metamétodo.
local Vec = {}
Vec.__index = Vec
local function V(x,y) return setmetatable({x=x,y=y},Vec) end
Vec.__tostring = function(v) return "("..v.x..","..v.y..")" end
Vec.__mul = function(a, b)
if type(a) == "number" then
return V(a*b.x, a*b.y) -- scalar * vec
elseif type(b) == "number" then
return V(a.x*b, a.y*b) -- vec * scalar
end
return a.x*b.x + a.y*b.y -- dot product
end
print(tostring(V(1,2) * 3)) -- (3,6)
print(tostring(3 * V(1,2))) -- (3,6)Verificação Rápida
Qual metamétodo é acionado por -myTable?
Recapitulação: Metamétodos Aritméticos
Resumo:
__add __sub __mul __div __mod __pow __idiv— aritmética binária__unm— menos unário;__len— operador #__concat— operador..__eq __lt __le— operadores de comparação- Trate tipos mistos (número/tabela) dentro dos metamétodos
Perguntas Frequentes
A aula “Metamétodos aritméticos” é grátis?
Sim — o texto completo de “Metamétodos aritméticos” é grátis para ler aqui na web. Para praticá-la interativamente (um editor de código integrado e um tutor de IA 24/7) e desbloquear o restante do curso de Lua Academy, atualize para CoddyKit PRO. O curso de Lua Academy inclui 4 aulas no total.
O que vou aprender em “Metamétodos aritméticos”?
Sobrecarregue +, -, *, / e outros operadores com metamétodos. Você pratica Lua Academy com código prático que executa diretamente no navegador, e um tutor de IA 24/7 responde suas dúvidas enquanto trabalha na aula.
Preciso ter experiência prévia para começar Lua Academy?
Nenhuma experiência prévia é necessária. Lua Academy no CoddyKit é estruturado para alunos iniciantes até avançados, então você pode começar aqui ou desde o início e aprender no seu ritmo. Esta é a aula 3 de 4.
Quanto tempo leva a aula “Metamétodos aritméticos”?
A maioria das aulas CoddyKit leva cerca de 5–10 minutos. Cada uma é compacta e interativa, então você faz progresso constante e retoma exatamente de onde parou entre web e app.
Posso escrever e executar código nesta aula de Lua Academy?
Sim. Cada aula de Lua Academy inclui um editor de código integrado, então você escreve e executa código real direto no navegador e recebe feedback de IA instantaneamente — nenhuma configuração local necessária.
Todas as aulas deste curso
- Introdução às metatabelas
- __index e __newindex
- Metamétodos aritméticos
- __tostring e __len