Funktionen & Multi-Return
Lua-Funktionen: First-Class Values, mehrere Rueckgaben, Closures, Default-Argumente und Variadic-Parameter mit ...
Inhaltsverzeichnis
Funktionen & Multi-Return
Funktionen sind das Rueckgrat von Lua. Sie sind First-Class Values - du kannst sie in Variablen speichern, als Argumente uebergeben und aus anderen Funktionen zurueckgeben.
Grundform
local function gruessen(name)
print("Hallo, " .. name .. "!")
end
gruessen("Anna")
Gleich wie:
local gruessen = function(name)
print("Hallo, " .. name .. "!")
end
Die erste Form ist haeufiger - sie ist nur syntaktischer Zucker fuer die zweite.
Rueckgabewert
local function addieren(a, b)
return a + b
end
print(addieren(3, 4)) -- 7
Ohne return gibt die Funktion nil zurueck (oder genauer: gar nichts).
Mehrere Rueckgabewerte
Ein Lua-Highlight: Funktionen koennen beliebig viele Werte zurueckgeben:
local function min_max(zahlen)
local min = zahlen[1]
local max = zahlen[1]
for i = 2, #zahlen do
if zahlen[i] < min then min = zahlen[i] end
if zahlen[i] > max then max = zahlen[i] end
end
return min, max
end
local lo, hi = min_max({3, 1, 4, 1, 5, 9, 2})
print(lo, hi) -- 1 9
Werte โverschluckenโ
Wenn du weniger Variablen angibst, werden ueberschuessige Werte verworfen:
local a, b = min_max({1, 2, 3}) -- a, b bekommen die Werte
local x = min_max({1, 2, 3}) -- nur min, max wird verworfen
Werte explizit in Klammern
Mit Klammern um den Funktionsaufruf bekommst du nur den ersten Wert:
local count = select("#", min_max({1, 2, 3})) -- 2 (2 Rueckgaben)
local nur_min = (min_max({1, 2, 3})) -- nur min
Merkwuerdig, aber gelegentlich nuetzlich.
Default-Werte
Lua hat keine echten Default-Werte, aber das or-Idiom hilft:
local function gruessen(name, gruss)
gruss = gruss or "Hallo"
print(gruss .. ", " .. name .. "!")
end
gruessen("Anna") -- "Hallo, Anna!"
gruessen("Max", "Moin") -- "Moin, Max!"
Aber Vorsicht: Wenn der Nutzer explizit false uebergibt, wird das zu โHalloโ - weil false falsy ist. Fuer false als legitimen Wert:
local function setze(aktiv)
if aktiv == nil then aktiv = true end
-- ...
end
Variadic Parameter mit ...
Beliebig viele Argumente:
local function summe(...)
local total = 0
for _, v in ipairs({...}) do
total = total + v
end
return total
end
print(summe(1, 2, 3)) -- 6
print(summe(1, 2, 3, 4, 5)) -- 15
Das ... ist ein spezielles Symbol in Lua - alle zusaetzlichen Argumente.
{...} und select
local function demo(...)
local args = {...} -- als Table
print("Anzahl:", #args)
print("Erstes:", args[1])
-- Alternative: select
print("Anzahl:", select("#", ...))
print("Ab 2.:", select(2, ...))
end
demo("a", "b", "c")
Keyword-Argumente durch Tables
Lua hat keine Keyword-Args - aber du kannst eine Table uebergeben:
local function nutzer_anlegen(opts)
local name = opts.name
local alter = opts.alter or 0
local rolle = opts.rolle or "user"
-- ...
end
nutzer_anlegen {
name = "Anna",
alter = 28,
rolle = "admin"
}
Das ist ein gelaeufiges Lua-Muster und wirkt fast wie Keyword-Args.
Kleines Detail: Wenn du nur eine Table als Argument uebergibst, kannst du die Klammern weglassen:
nutzer_anlegen { name = "Anna", alter = 28 }
Funktionen als Werte
Funktionen kannst du wie alle anderen Werte behandeln:
local f = print
f("Hallo") -- funktioniert
local function anwenden(fn, wert)
return fn(wert)
end
print(anwenden(math.sqrt, 16)) -- 4.0
print(anwenden(string.upper, "abc")) -- "ABC"
Anonyme Funktionen
local verdoppelt = table.pack()
local function jedem_zahl(tbl, fn)
for _, v in ipairs(tbl) do
print(fn(v))
end
end
jedem_zahl({1, 2, 3, 4, 5}, function(n) return n * 2 end)
-- 2, 4, 6, 8, 10
Closures
Funktionen fangen Variablen aus ihrem Scope ein:
local function macheZaehler()
local n = 0
return function()
n = n + 1
return n
end
end
local z = macheZaehler()
print(z()) -- 1
print(z()) -- 2
print(z()) -- 3
local z2 = macheZaehler()
print(z2()) -- 1 (eigener Counter!)
Jeder Aufruf von macheZaehler erzeugt ein neues n.
Rekursion
local function fakultaet(n)
if n <= 1 then return 1 end
return n * fakultaet(n - 1)
end
print(fakultaet(5)) -- 120
Lua optimiert Tail Calls - reine rekursive Endaufrufe blasen den Stack nicht auf:
local function loop(i, n)
if i > n then return end
print(i)
return loop(i + 1, n) -- Tail Call - wird optimiert
end
loop(1, 1000000) -- laeuft, kein Stack Overflow
Methoden-Syntax mit :
Fuer Tables mit methoden-artigen Funktionen:
local person = { name = "Anna", alter = 28 }
function person:gruessen()
print("Hallo, ich bin " .. self.name)
end
person:gruessen() -- "Hallo, ich bin Anna"
Der Doppelpunkt : uebergibt person implizit als erstes Argument namens self.
Das ist gleich mit:
function person.gruessen(self)
print("Hallo, ich bin " .. self.name)
end
person.gruessen(person) -- gleicher Effekt
Mehr dazu im Tables-Kapitel.
Praktisches Beispiel
local function nutzer_formatieren(opts)
local name = opts.name or "Anonym"
local alter = opts.alter
local rollen = opts.rollen or {}
local format = opts.format or function(t) return t end
local teile = {name}
if alter then table.insert(teile, alter .. " Jahre") end
if #rollen > 0 then table.insert(teile, table.concat(rollen, ", ")) end
return format(table.concat(teile, " - "))
end
print(nutzer_formatieren {
name = "Anna",
alter = 28,
rollen = {"admin"}
})
-- Anna - 28 Jahre - admin
print(nutzer_formatieren {
name = "Max",
format = function(t) return "[" .. t:upper() .. "]" end
})
-- [MAX]
Zusammenfassung
local function name(params) ... end- kompakt und idiomatisch- Mehrere Rueckgabewerte sind eingebaut -
local a, b = f() ...fuer variadic Args -{...}oderselect("#", ...)zum Zaehlen- Table-Parameter ersetzen Keyword-Args
- Funktionen sind Werte - uebergeben, zurueckgeben, in Tables speichern
- Closures fangen Variablen ein
:-Syntax fuer Methoden - implicitself-Parameter
Im naechsten Kapitel: Tables, Metatables und wie du OOP in Lua baust.