Zum Inhalt springen
Lua Anfรคnger 25 min

Funktionen & Multi-Return

Lua-Funktionen: First-Class Values, mehrere Rueckgaben, Closures, Default-Argumente und Variadic-Parameter mit ...

Aktualisiert:
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 - {...} oder select("#", ...) zum Zaehlen
  • Table-Parameter ersetzen Keyword-Args
  • Funktionen sind Werte - uebergeben, zurueckgeben, in Tables speichern
  • Closures fangen Variablen ein
  • :-Syntax fuer Methoden - implicit self-Parameter

Im naechsten Kapitel: Tables, Metatables und wie du OOP in Lua baust.

Zurรผck zum Lua Kurs