Metametodi aritmetici
Ridefinisca +, -, *, / e altri operatori con i metametodi.
Metametodi aritmetici è una lezione Lua Academy gratuita su CoddyKit. Questa è la lezione 3 di 4. Puoi leggere la lezione completa qui gratuitamente — poi esercitati direttamente nel browser con un editor di codice integrato e un tutor IA disponibile 24/7. Fa parte del percorso di apprendimento Lua Academy, e i tuoi progressi si sincronizzano tra il web e l'app CoddyKit. Il corso Lua Academy include 4 lezioni in totale.
Nomi dei metametodi
Lua definisce metametodi per tutti gli operatori aritmetici. Quando Lua rileva un'operazione aritmetica su una tabella, cerca il metametodo corrispondente nella metatabella della tabella. Se entrambi gli operandi sono tabelle, Lua controlla prima la metatabella dell'operando sinistro.
-- 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 per la somma di vettori
Definisca __add su una tabella vettore per supportare +. Il metametodo riceve due operandi e restituisce un nuovo valore. Entrambi gli operandi potrebbero essere tabelle oppure uno potrebbe essere un numero: il metametodo dovrebbe gestire entrambi i casi.
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
Definisca in modo analogo __sub, __mul e __div. Per la moltiplicazione, gestisca sia i casi tabella*tabella sia tabella*numero controllando i tipi degli operandi all'interno del metametodo.
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: negazione unaria
__unm è il metametodo della negazione unaria, invocato quando Lua valuta -obj. Riceve l'operando (lo stesso valore passato due volte per coerenza) e restituisce il valore negato.
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 per una lunghezza personalizzata
__len viene chiamato quando si valuta #obj su una tabella priva di una sequenza intera grezza. Lo definisca affinché restituisca una "lunghezza" significativa per tipi personalizzati come set, code o contenitori pesati.
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 gestisce l'operatore %; __pow gestisce ^. Sono operatori meno comuni, ma utili per tipi numerici personalizzati come interi grandi, frazioni o oggetti per l'aritmetica modulare.
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 viene attivato dall'operatore .. quando almeno uno degli operandi dispone di questo metametodo. Ciò consente di definire la concatenazione per tipi personalizzati o di creare DSL fluenti.
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())Metametodi di confronto
__eq definisce == per le tabelle (viene chiamato solo quando entrambi gli operandi hanno la stessa metatabella). __lt definisce <; __le definisce <=. Nota: ~= usa __eq; > usa __lt con gli argomenti invertiti; >= 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)Concatenazione dei metametodi
Poiché i metametodi restituiscono valori (di solito nuove tabelle), le operazioni possono essere concatenate naturalmente. Ogni operatore restituisce un nuovo oggetto e l'operatore successivo usa quel risultato. Questo consente di scrivere espressioni aritmetiche fluenti su tipi personalizzati.
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)Operazioni su tipi misti
Quando scrive vec * 2, l'operando sinistro è la tabella. Quando scrive 2 * vec, l'operando sinistro è un numero (privo di metametodo), quindi Lua controlla la metatabella dell'operando destro per cercare __mul. Gestisca entrambi gli ordinamenti nel metametodo.
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 rapida
Quale metametodo viene attivato da -myTable?
Riepilogo: metametodi aritmetici
Riepilogo:
__add __sub __mul __div __mod __pow __idiv— aritmetica binaria__unm— negazione unaria;__len— operatore #__concat— operatore..__eq __lt __le— operatori di confronto- Gestisca i tipi misti (numero/tabella) all'interno dei metametodi
Domande Frequenti
La lezione «Metametodi aritmetici» è gratuita?
Sì — il testo completo di «Metametodi aritmetici» è gratuito qui sul web. Per esercitarvi in modo interattivo (un editor di codice integrato e un tutor IA 24/7) e sbloccare il resto del corso Lua Academy, passa a CoddyKit PRO. Il corso Lua Academy include 4 lezioni in totale.
Cosa imparerò in «Metametodi aritmetici»?
Ridefinisca +, -, *, / e altri operatori con i metametodi. Eserciti Lua Academy con codice pratico che esegui direttamente nel browser, e un tutor IA 24/7 risponde alle tue domande mentre lavori sulla lezione.
Ho bisogno di esperienza per iniziare Lua Academy?
Non è richiesta alcuna esperienza precedente. Lua Academy su CoddyKit è strutturato per principianti e studenti avanzati, quindi puoi iniziare da qui o dall'inizio e procedere al tuo ritmo. Questa è la lezione 3 di 4.
Quanto tempo richiede la lezione «Metametodi aritmetici»?
La maggior parte delle lezioni CoddyKit richiede circa 5–10 minuti. Ogni lezione è breve e interattiva, quindi fai progressi costanti e riprendi esattamente da dove hai lasciato su web e app.
Posso scrivere ed eseguire codice in questa lezione Lua Academy?
Sì. Ogni lezione Lua Academy include un editor di codice integrato, quindi scrivi ed esegui codice reale direttamente nel tuo browser e ricevi feedback istantaneo dall'IA — nessuna configurazione locale necessaria.
Tutte le lezioni di questo corso
- Introduzione alle metatabelle
- __index e __newindex
- Metametodi aritmetici
- __tostring e __len