Lua Academy · Les

Rekenkundige metamethoden

Laad +, -, *, / en andere operatoren opnieuw met metamethoden

Les 3 van 412 stappen

Rekenkundige metamethoden is een gratis Lua Academy-les op CoddyKit. Dit is les 3 van 4. Je kunt 3 lessen uit dit leerpad gratis volledig lezen — daarna ontgrendelt CoddyKit PRO alle lessen, plus praktische oefeningen met een ingebouwde code-editor en een AI-tutor die 24/7 beschikbaar is. Deze les maakt deel uit van het leertraject Lua Academy. Je voortgang wordt gesynchroniseerd op het web en in de CoddyKit-app. De cursus Lua Academy bevat in totaal 4 lessen.

Namen van metamethoden

Lua definieert metamethoden voor alle rekenkundige operatoren. Wanneer Lua een rekenkundige bewerking op een tabel ziet, zoekt het naar de bijbehorende metamethode in de metatabel van de tabel. Als beide operanden tabellen zijn, controleert Lua eerst de metatabel van de linkeroperand.

-- 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 voor optellen van vectoren

Definieer __add op een vectortabel om + te ondersteunen. De metamethode ontvangt twee operanden en retourneert een nieuwe waarde. Beide operanden kunnen tabellen zijn, of één ervan kan een getal zijn — je metamethode moet beide gevallen afhandelen.

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

Definieer __sub, __mul en __div op dezelfde manier. Handel voor vermenigvuldiging zowel de gevallen tabel*tabel als tabel*getal af door de operandtypen binnen de metamethode te controleren.

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 unaire min

__unm is de metamethode voor unaire min en wordt aangeroepen wanneer Lua -obj evalueert. De methode ontvangt de operand (voor consistentie tweemaal dezelfde waarde) en retourneert de tegengestelde waarde.

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 voor aangepaste lengtes

__len wordt aangeroepen wanneer #obj wordt geëvalueerd voor een tabel zonder onbewerkte gehele getallenreeks. Definieer deze methode om een betekenisvolle 'lengte' te retourneren voor aangepaste typen zoals verzamelingen, wachtrijen of gewogen containers.

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 en __pow

__mod verwerkt de operator %; __pow verwerkt ^. Deze worden minder vaak gebruikt, maar zijn nuttig voor aangepaste numerieke typen zoals grote gehele getallen, breuken of objecten voor modulaire rekenkunde.

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 wordt geactiveerd door de operator .. wanneer ten minste één operand deze metamethode heeft. Zo kun je concatenatie voor aangepaste typen definiëren of vloeiende DSL's maken.

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())

Metamethoden voor vergelijkingen

__eq definieert == voor tabellen (alleen aangeroepen wanneer beide operanden dezelfde metatabel hebben). __lt definieert <; __le definieert <=. Let op: ~= gebruikt __eq; > gebruikt __lt met omgekeerde argumenten; >= gebruikt __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)

Metamethoden koppelen

Omdat metamethoden waarden retourneren (meestal nieuwe tabellen), kunnen bewerkingen op natuurlijke wijze worden gekoppeld. Elke operator retourneert een nieuw object en de volgende operator gebruikt dat resultaat. Zo kun je vloeiende rekenkundige expressies voor aangepaste typen maken.

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)

Bewerkingen met gemengde typen

Wanneer je vec * 2 schrijft, is de linkeroperand de tabel. Wanneer je 2 * vec schrijft, is de linkeroperand een getal (zonder metamethode), dus controleert Lua de metatabel van de rechteroperand op __mul. Handel beide volgordes in je metamethode af.

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)

Korte controle

Welke metamethode wordt geactiveerd door -myTable?

Samenvatting: rekenkundige metamethoden

Samenvatting:

  • __add __sub __mul __div __mod __pow __idiv — binaire rekenkunde
  • __unm — unaire min; __len — operator #
  • __concat — operator ..
  • __eq __lt __le — vergelijkingsoperatoren
  • Handel gemengde typen (getal/tabel) af binnen metamethoden
Gratis beginnen

Leer Lua met een AI-tutor — gratis

Schrijf echte code en voer die uit in je browser, krijg direct hulp van een AI-tutor die 24/7 beschikbaar is en ga verder waar je gebleven bent op het web of in de app.

Cursussen
40
Lessen
159

Veelgestelde vragen

Is de les “Rekenkundige metamethoden” gratis?

Ja — je kunt hier op het web alle 3 lessen van het leerpad Lua Academy, waaronder “Rekenkundige metamethoden”, gratis volledig lezen. Daarna ontgrendelt CoddyKit PRO alle lessen, plus interactieve oefeningen met een ingebouwde code-editor en een AI-tutor die 24/7 beschikbaar is. De cursus Lua Academy bevat in totaal 4 lessen.

Wat leer ik in “Rekenkundige metamethoden”?

Laad +, -, *, / en andere operatoren opnieuw met metamethoden Je oefent met Lua Academy door code rechtstreeks in de browser uit te voeren. Een AI-begeleider die 24/7 beschikbaar is beantwoordt je vragen terwijl je de les doorwerkt.

Heb ik ervaring nodig om met Lua Academy te beginnen?

Ervaring vooraf is niet nodig. Lua Academy op CoddyKit is opgebouwd voor beginners tot gevorderden, zodat je hier of bij het begin kunt starten en in je eigen tempo kunt leren. Dit is les 3 van 4.

Hoe lang duurt de les “Rekenkundige metamethoden”?

De meeste lessen van CoddyKit duren ongeveer 5–10 minuten. Elke les is kort en interactief, zodat je gestaag vooruitgaat en op het web en in de app precies verdergaat waar je was gebleven.

Kan ik code schrijven en uitvoeren in deze les over Lua Academy?

Ja. Elke les over Lua Academy bevat een ingebouwde code-editor, zodat je rechtstreeks in je browser echte code kunt schrijven en uitvoeren en direct feedback van AI krijgt — lokale installatie is niet nodig.

Alle lessen in deze cursus

  1. Kennismaking met metatables
  2. __index en __newindex
  3. Rekenkundige metamethoden
  4. __tostring en __len
← Terug naar Lua Academy