Bei Lua handelt es sich um eine in Brasilien Anfang der 90er-Jahre ent­wi­ckel­te Script-Sprache. Der Quelltext eines Lua-Programms wird vom Lua-In­ter­pre­ter in Bytecode übersetzt und aus­ge­führt. Der In­ter­pre­ter selbst ist in C ge­schrie­ben, was Lua-Pro­gram­men in der Aus­füh­rung zu hoher Per­for­manz verhilft. Ferner er­mög­licht das C-API es, Lua-Code in C/C++ Pro­gram­men ein­zu­bet­ten. Lua ist eine Mul­ti­pa­ra­dig­men­spra­che, die sich zum Schreiben von im­pe­ra­ti­vem, funk­tio­na­lem und ob­jekt­ori­en­tier­tem Code eignet.

Das stärkste Al­lein­stel­lungs­merk­mal von Lua ist die einfache Ein­bet­tung in andere Systeme und Sprachen. Lua hat sich damit als „Glue Language“ etabliert und kommt in vielen Game-Engines zum Einsatz. Die Sprache lässt sich zudem zur Steuerung von Web­ser­vern wie Apache und nginx nutzen. Über die CGI-Schnitt­stel­le wird Lua oft auch als ei­gen­stän­di­ge Internet-Pro­gram­mier­spra­che verwendet. Ferner kommt die Sprache zur Ent­wick­lung mobiler Apps zum Einsatz.

Lua Scripting Tutorial: Die ersten Schritte

Der ein­fachs­te und schnells­te Weg, mit Lua pro­gram­mie­ren zu lernen, besteht darin, Lua-Code auf der in­ter­ak­ti­ven Lua-Demo-Seite aus­zu­füh­ren. Sie können alle im weiteren Verlauf des Artikels dar­ge­stell­ten Lua-Code-Beispiele testen. Kopieren Sie eines der Code-Beispiele in das Textfeld und klicken Sie auf „run“, um den Code aus­zu­füh­ren.

Auf diesem Weg sparen Sie sich die In­stal­la­ti­on. Sollten Sie Lua auf dem eigenen System nutzen wollen, folgen Sie unseren weiteren An­wei­sun­gen. An­dern­falls gehen Sie gleich weiter zum Abschnitt „Die Grund­la­gen der Lua-Script­spra­che erlernen“.

Das eigene System für das Lua-Tutorial vor­be­rei­ten

Der Lua-In­ter­pre­ter besteht aus einer einzigen Bi­när­da­tei, die auf der Kom­man­do­zei­le nach dem Befehl „lua“ be­reit­steht. Diese wird auf dem System abgelegt und muss ggf. in den Pfad auf­ge­nom­men werden. Ferner bietet Lua Bi­blio­the­ken, die die Ein­bet­tung von Lua-Code in C/C++ Pro­gram­men er­mög­li­chen.

Für die In­stal­la­ti­on unter Mac und Linux bietet sich die In­stal­la­ti­on mit dem „Homebrew“-Pa­ket­ma­na­ger an. Wenn Sie auf Ihrem System Homebrew in­stal­liert haben, nutzen Sie am besten den folgenden Befehl auf der Kom­man­do­zei­le, um Lua zu in­stal­lie­ren:

brew install lua

Um Lua auf einem Windows-System zu in­stal­lie­ren bietet sich der LuaDist-Installer an.

Den Lua-In­ter­pre­ter in­ter­ak­tiv nutzen

Wie bei vielen Script-Sprachen üblich, lässt sich der Lua-In­ter­pre­ter in­ter­ak­tiv ausführen. Im in­ter­ak­ti­ven Modus nimmt der In­ter­pre­ter auf der Kom­man­do­zei­le Lua-Code entgegen und führt diesen zei­len­wei­se aus. Die dabei erzeugte Werte werden direkt auf der Kom­man­do­zei­le aus­ge­ge­ben. Als Nutzer kann man dann die Werte von Variablen über­prü­fen und ändern. Somit eignet sich dieser Ansatz besonders zum schnellen Pro­to­ty­pi­sie­ren. Um den Lua-In­ter­pre­ter im in­ter­ak­ti­ven Modus zu starten, führen wir auf der Kom­man­do­zei­le den folgenden Befehl aus:

# Lua-Interpreter im interaktiven Modus starten
lua -i
Hinweis

Um den in­ter­ak­ti­ven Modus wieder zu verlassen, geben Sie den Befehl „os.exit()“ ein, oder drücken Sie die Tasten [Strg]+[D] in Kom­bi­na­ti­on.

Lua-Script für das Tutorial mit dem Lua-In­ter­pre­ter ausführen

Anstatt Lua-Code auf der Kom­man­do­zei­le Stück für Stück ein­zu­ge­ben, können Sie den Lua-In­ter­pre­ter auch anweisen, eine komplette Lua-Quell­text­da­tei aus­zu­füh­ren. Dafür erzeugen wir zunächst eine Lua-Datei und übergeben dem Lua-In­ter­pre­ter den Da­tei­na­men zur Aus­füh­rung. Der In­ter­pre­ter liest den in der Datei ent­hal­te­nen Quelltext Zeile für Zeile ab und führt diesen aus.

# Lua-Script ausführen
lua <dateiname>.lua
Hinweis

Lua-Quell­text­da­tei­en enden mit der Da­tei­er­wei­te­rung „.lua“.

Lua-Script für das Tutorial mittels Hashbang direkt aus­führ­bar machen

Auf den Be­triebs­sys­te­men Linux / UNIX / macOS haben wir auch die Mög­lich­keit, eine Lua-Quell­text­da­tei direkt aus­führ­bar zu machen. Dazu tragen wir einen so genannten „Hashbang“ als erste Zeile der Lua-Datei ein:

#!/usr/local/bin/lua
-- Lua Code für die Ausführung

Wie Sie sehen, enthält der Hashbang den Spei­cher­ort der Lua-Bi­när­da­tei, in unserem Fall ‚#!/usr/local/bin/lua‘. Unter Umständen weicht der Spei­cher­ort auf Ihrem lokalen System davon ab. In diesem Fall können Sie den Spei­cher­ort der Lua-Bi­när­da­tei ermitteln. Nutzen Sie dazu den „which“-Befehl auf der Kom­man­do­zei­le:

# Speicherort der Lua-Binärdatei ermitteln
which lua

Nachdem Sie ein Lua-Script mit dem Hashbang versehen haben, müssen Sie die Datei als durch den Nutzer aus­führ­bar markieren. Nutzen Sie dafür den folgenden Befehl auf der Kom­man­do­zei­le:

# Lua-Datei als ausführbar markieren
chmod u+rx <dateiname>.lua

Führen Sie das Lua-Script dann im aktuellen Ver­zeich­nis aus:

./<dateiname>.lua
Tipp

Der Hashbang-Trick funk­tio­niert auf Linux und UNIX-artigen Systemen wie macOS mit den meisten Script-Sprachen. Sie können nach dem selben Schema Ruby- oder Python-Scripte direkt aus­führ­bar machen.

Die Grund­la­gen der Lua-Script-Sprache erlernen

Bei Lua handelt es sich um eine Mul­ti­pa­ra­dig­men­spra­che; der grund­le­gen­de Stil ist imperativ und funk­tio­nal. Die Sprache ist komplett dynamisch, d.h. es wird keine Un­ter­schei­dung zwischen „compile time“ und „run time“ gemacht. Lua setzt aus­nahms­los auf dy­na­mi­sche Spei­cher­ver­wal­tung: die Größe eines Objekts im Speicher kann sich während der Laufzeit ändern. Ein „Garbage Collector“ (GC) räumt nicht mehr be­nö­tig­ten Spei­cher­platz wieder frei, sodass der Pro­gram­mie­rer sich nicht darum kümmern muss.

Kom­men­ta­re in Lua-Scripten nutzen lernen

Kom­men­ta­re sind es­sen­zi­el­ler Be­stand­teil einer jeden Pro­gram­mier­spra­che. Sie werden unter anderem für die folgenden Zwecke genutzt:

  • Code-Be­stand­tei­le skiz­zie­ren
  • Code-Features do­ku­men­tie­ren
  • Code-Zeilen ak­ti­vie­ren / de­ak­ti­vie­ren

Ein ein­zei­li­ger Kommentar in Lua beginnt mit einem doppelten Bin­de­strich (--) und läuft bis zum Ende der Zeile:

-- diese Zeile wird vom Interpreter ignoriert

In Kom­bi­na­ti­on mit doppelten eckigen Klammern „[[“ und „]]“ lassen sich auch mehr­zei­li­ge Kom­men­ta­re schreiben:

--[[
Dieser Kommentar
erstreckt sich über
mehrere Zeilen.
]]

Werte und Typen für das Lua-Scripting-Tutorial

Wie die meisten anderen Script-Sprachen ist auch Lua eine dynamisch ty­pi­sier­te Sprache. Typen gehören nicht zu Variablen, sondern zu Werten. Jeder Wert hat genau einen Typ, sei es Zahl, Zei­chen­fol­ge, Wahr­heits­wert etc. Insgesamt verfügt Lua über eine über­schau­ba­re Anzahl an Typen. Diese sind in der folgenden Übersicht zu­sam­men­ge­fasst:

Typ Erklärung
number De­zi­mal­zahl
string Zei­chen­fol­ge
boolean Wahr­heits­wert: „true“ oder „false“
nil Fehlender Wert; Typ hat nur den Wert „nil“
function Funktion
table Zu­sam­men­ge­setz­ter Datentyp: Liste / Array, Hash / Dic­tion­a­ry
thread Co­rou­ti­nen
userdata Benutzer-de­fi­nier­ter C-Datentyp

Lua kennt Literal-Syntax für Werte aller Typen mit Ausnahme von „thread“ und „userdata“. Um den Typ eines Werts zu ermitteln, nutzen wir die „type()“-Funktion. Diese gibt den Namen des Typs als String zurück. Hier ein paar Beispiele:

type(42) -- Typ ist `number`
type("Lua Tutorial") -- Typ ist `string`
type(false) -- Typ ist `boolean`
type(var) -- Typ ist `nil`, da `var` nicht definiert ist
Hinweis

Beachten Sie bei den folgenden Code-Bei­spie­len, dass in Lua das erste Element einer Liste den Index 1 hat anstelle 0, wie in den meisten Sprachen üblich!

Mit Lua Pro­gram­mie­ren lernen: Was sind Ausdrücke, Variablen und Ope­ra­to­ren?

Ein Ausdruck („Ex­pres­si­on“) wird vom In­ter­pre­ter evaluiert und liefert einen Wert zurück. Ausdrücke kom­bi­nie­ren Literale, Ope­ra­to­ren, Variablen und Funk­ti­ons­auf­ru­fe. Ausdrücke können optional mit Klammern „()“ gruppiert werden. Als dy­na­mi­sche Sprache ermittelt Lua den Typ des zu­rück­ge­ge­be­nen Werts au­to­ma­tisch. Hier einige Beispiele für Ausdrücke:

-- Arithmetische Operation in Lua
1 + 2 -- evaluiert zum Wert `3`
-- String-Konkatenation in Lua
'Walther' .. 'White' -- evaluiert zu `WaltherWhite`
-- String-Konkatenation mit automatischer Umwandlung einer Zahl in Lua
'Die ' .. 3 .. ' Musketiere' -- evaluiert zu `Die 3 Musketiere`
-- Gleichheits-Test in Lua
7 == '7' -- evaluiert zu `false`
-- Gleichheits-Test in Lua
'klein' == string.lower('KLEIN') -- evaluiert zu `true`
-- dynamische Typ-Information
type(var) == 'nil' -- evaluiert zu `true`, da `var` nicht definiert

Eine Variable ist ein Name für einen Wert im Speicher. Wie in den meisten Pro­gram­mier­spra­chen beginnt ein Name in Lua mit einem Buch­sta­ben oder Un­ter­strich (_), gefolgt von weiteren Buch­sta­ben, Un­ter­stri­chen oder Zahlen. Dabei wird streng zwischen Groß- und Klein­schrei­bung un­ter­schie­den. Die folgenden re­ser­vier­ten Wörter dürfen für sich alleine nicht als Name verwendet werden:

„and“, „end“, „in“, „repeat“, „break“, „false“, „local“, „return“, „do“, „for“, „nil“, „then“, „else“, „function“, „not“, „true“, „elseif“, „if“, „or“, „until“, „while“

Al­ler­dings können die re­ser­vier­ten Wörter pro­blem­los als Teil eines Namens auftreten:

for = "Peter" -- ruft Fehler hervor
for_user = "Peter" -- erlaubt

Die Zuweisung eines Werts an eine Variable erfolgt über den Zu­wei­sungs-Operator (=). Nicht zu ver­wech­seln ist dieser mit dem logischen Gleich­heits-Operator (==). Bei der Zuweisung wird wie üblich zwischen „L-value“ und „R-value“ un­ter­schie­den: die Variable muss auf der linken Seite des Zu­wei­sungs-Operators stehen, ist also der L-value. Diesem wird der eva­lu­ier­te Wert des rechts stehenden R-value zu­ge­wie­sen:

anzahl = 13 -- das ist OK
13 = anzahl -- ruft Fehler hervor, da der Zahl 13 kein neuer Wert zugewiesen werden kann

Ein Operator erzeugt einen neuen Wert aus einem oder mehreren Operanden. Dabei spricht man von einem unären (ein­stel­li­gen) oder binären (zwei­stel­li­gen) Operator. Ein Operator verknüpft Operanden eines be­stimm­ten Typs und liefert einen Wert eines be­stimm­ten Typs zurück. Schauen wir uns die ver­schie­de­nen Ope­ra­to­ren in Lua an.

Arith­me­ti­sche Ope­ra­to­ren operieren auf Zahlen und liefern eine Zahl zurück:

Arith­me­ti­sche Operator Arität Operation
+ binär Addition
- binär Sub­trak­ti­on
* binär Mul­ti­pli­ka­ti­on
/ binär Division
% binär Modulus
^ binär Po­ten­zie­rung
- unär Negation

Die re­la­tio­na­len Ope­ra­to­ren sind allesamt binär und testen, wie sich zwei Operanden zu­ein­an­der verhalten. Sie liefern einen Wahr­heits­wert zurück:

Re­la­tio­na­ler Operator Test
== Gleich­heit
~= Un­gleich­heit
> Größer als
< Kleiner als
>= Größer als oder gleich
<= Kleiner als oder gleich

Logische Ope­ra­to­ren ver­knüp­fen Wahr­heits­wer­te und liefern einen neuen Wahr­heits­wert zurück:

Logischer Operator Arität Operation
and binär UND-Ver­knüp­fung
or binär ODER-Ver­knüp­fung
not unär Negation

Neben den genannten gibt es noch zwei spezielle Ope­ra­to­ren in Lua. Diese dienen zur Kon­ka­te­na­ti­on von Strings (also ihrer Ver­ket­tung) sowie zur Er­mitt­lung der Mäch­tig­keit eines zu­sam­men­ge­setz­ten Werts, wie Table oder String:

Operator Arität Operation
.. binär String-Kon­ka­te­na­ti­on
# unär Anzahl Elemente eines Tables / Länge eines Strings ermitteln

Lua kennt keine zu­sam­men­ge­setz­ten Zu­wei­sungs-Ope­ra­to­ren wie „+=“ und „-=“, die in vielen Script-Sprachen üblich sind. Zum In­kre­men­tie­ren und De­kre­men­tie­ren von Variablen wird die Operation explizit aus­ge­schrie­ben:

preis = 42.99
rabatt = 0.15 -- 15% Rabatt
preis -= preis * rabatt -- `-=` funktioniert in Lua nicht
-- Dekrementierung muss stattdessen explizit geschrieben werden
preis = preis - (preis * rabatt)

Gül­tig­keits­be­rei­che und Blöcke für das Lua Script-Tutorial verstehen

Das Konzept des Gül­tig­keits­be­reichs ist ein zentrales Konzept einer jeden Pro­gram­mier­spra­che. Eine Variable existiert nur innerhalb eines be­stimm­ten Gül­tig­keits­be­reichs. Wie in Ja­va­Script sind Variablen in Lua per Vor­ein­stel­lung global. Jedoch ist die durch­ge­hen­de Nutzung globaler Variablen als „Anti-Pattern“ bekannt und sollte vermieden werden. In Lua schafft das „local“-Schlüs­sel­wort Abhilfe. Mit diesem wird der Gül­tig­keits­be­reich einer Variable auf den um­ge­ben­den Block be­schränkt – ver­gleich­bar mit der De­kla­ra­ti­on via „let“ in Ja­va­Script.

-- diese Variable ist global
x = 5
-- lokale Variable definieren
local z = 10

Die Körper von Funk­tio­nen und Schleifen öffnen in Lua einen neuen Gül­tig­keits­be­reich. Ferner nutzt Lua das Konzept des ex­pli­zi­ten Blocks. Ein Block definiert einen neuen Gül­tig­keits­be­reich für den zwischen den Schlüs­sel­wör­tern „do“ und „end“ stehenden Code. Dies ent­spricht den öffnenden/schlie­ßen­den Klammern „{“ und „}“ in Java/C/C++. Das folgende Code-Beispiel ver­deut­licht, wie Blöcke, Gül­tig­keits­be­rei­che und Variablen zu­sam­men­hän­gen:

-- äußerer Gültigkeitsbereich
do
    local x = 1
    do -- innerer Gültigkeitsbereich
        local y = 2
        -- `z` im globalen Gültigkeitsbereich erzeugen
        -- dabei Zugriff auf lokale Variable `x` von äußerem Gültigkeitsbereich
        -- sowie lokale Variable `y` vom inneren Gültigkeitsbereich
        z = x + y -- `z` hat jetzt den Wert `3`
    end
    print(x) -- gibt `1` aus
    print(y) -- gibt `nil` aus, da `y` im äußeren Gültigkeitsbereich nicht existiert
    print(z) -- gibt `3` aus
end
-- `z` ist global, existiert also außerhalb des äußeren Gültigkeitsbereich
z = z + 4
print(z) -- gibt `7` aus

Mit den Lua-Kon­troll­struk­tu­ren Pro­gram­mie­ren lernen

Lua kennt die üblichen Kon­troll­struk­tu­ren, die man auch in anderen Pro­gram­mier­spra­chen findet. Dazu gehören die Ver­zwei­gun­gen und Schleifen. Hier ein Beispiel für Luas „if“-, „then“-, „else“-, „elseif“-An­wei­sun­gen:

limit = 42;
zahl = 43;
if zahl < limit then
    print("Unter dem Limit.")
elseif zahl == limit then
    print("Genau am Limit…")
else
    print("Über dem Limit!")
end

Neben der klas­si­schen „while“-Schleife erkennt Lua auch deren Ge­gen­stück „repeat“-„until“. Diese Anweisung findet man auch in Ruby. Sie erfordert die Umkehrung der ein­ge­setz­ten Kondition. Das heißt, ein „while“ mit Kondition „zahl </= limit“ ent­spricht einem „repeat“-„until“ mit Kondition „zahl > limit“. Vorsicht mit der „repeat“-Anweisung! Un­ab­hän­gig von der Kondition wird der Schlei­fen­kör­per min­des­tens einmal aus­ge­führt. Hier ein Beispiel:

limit = 10
zahl = 1
while zahl <= limit do
    print("Zahl:", zahl)
    zahl = zahl + 1
end
-- Achtung: obwohl `zahl` bereits größer als `limit`
-- wird der Schleifenkörper einmal ausgeführt
zahl = 11
repeat 
    print("Zahl:", zahl)
    zahl = zahl + 1
until zahl > limit

So wie die meisten im­pe­ra­ti­ven Pro­gram­mier­spra­chen kennt auch Lua neben der „while“-Schleife eine „for“-Anweisung. Dabei kommen zwei Formen zum Einsatz: eine C-ähnliche Variante mit Schleifen-Variable sowie eine Variante mit Iterator. Be­trach­ten wir zunächst die Nutzung der „for“-Anweisung mit Schleifen-Variable:

anfang = 1
ende = 10
for zahl = anfang, ende do
    print("Aktuelle Zahl:", zahl) -- `1,2,3,4,5,6,7,8,9,10`
end
-- explizit Schritt auf `2` setzen
schritt = 2
for zahl = anfang, ende, schritt do
    print("Aktuelle Zahl:", zahl) -- `1,3,5,7,9`
end
-- der Schritt kann auch negativ sein
schritt = -2
-- mit negativem Schritt Anfang und Ende vertauschen, um absteigend zu zählen
for zahl = ende, anfang, schritt do
    print("Aktuelle Zahl:", zahl) -- `10,8,6,4,2`
end

Über­ra­schen­der­wei­se ist die in der „for“-Schleife de­fi­nier­te Schleifen-Variable lokal, nicht global, ohne dass sie explizit als „local“ de­kla­riert werden müsste. Das ist sinnvoll, und dies­be­züg­lich un­ter­schei­det sich Lua positiv von Ja­va­Script. Dort ist eine ohne „let“ oder „var“ de­kla­rier­te Schleifen-Variable global, was zu schwer­wie­gen­den Fehlern führen kann.

Schauen wir uns nun Luas „for“-Schleife mit Iterator an. Prin­zi­pi­ell ähnelt der Ansatz dem von Python: Anstatt eine Schleifen-Variable zu in­kre­men­tie­ren und als Index in einer Liste zu nutzen, iterieren wir direkt über den Elementen der Liste. Zum Erzeugen des Iterators kommt häufig die „ipairs()“-Funktion zum Einsatz. Hier ein Beispiel:

-- Liste von Jahren definieren
dekaden = {1910, 1920, 1930, 1940, 1950, 1960, 1970, 1980, 1990}
-- mittels Iterator auf die einzelnen Jahre zugreifen
for index, jahr in ipairs(dekaden) do
    print(index, jahr)
end

Mehr über Funk­tio­nen mit Lua lernen

Funk­tio­nen werden wie in C/C++, Java und Ja­va­Script mit dem „function“-Schlüs­sel­wort definiert. Wie üblich folgen die Funk­ti­ons­pa­ra­me­ter in Klammern nach den Funk­ti­ons­na­men. Das Besondere bei Lua ist, dass beim Funk­ti­ons­auf­ruf mit genau einem Literal als Argument die Klammern weg­ge­las­sen werden dürfen. Eine Lua-Funktion muss nicht zwingend einen Wert zu­rück­ge­ben. Der De­fi­ni­ti­on nach handelt es sich ohne Wert um eine „Prozedur“:

-- Prozedur definieren
function hallo(name)
    print("Guten Tag", name)
end
-- Funktion aufrufen
hallo("der feine Herr")
-- auch dies ist möglich
hallo "der feine Herr"
-- folgendes funktioniert jedoch nicht
name = "Walther"
hallo name -- Syntax-Fehler
-- mit Variable statt Literal muss die Funktion mit Klammern aufgerufen werden
hallo(name)

Will man aus einer Funktion einen Wert zu­rück­zu­ge­ben, kommt wie üblich das „return“-Schlüs­sel­wort zum Einsatz. Dieses beendet die Aus­füh­rung der Funktion und gibt den an­ge­ge­be­nen Wert zurück. In folgendem Code-Beispiel wird eine Zahl quadriert:

-- Funktion mit einzelnem Rückgabewert
function quadrat(zahl)
    -- der Ausdruck `zahl * zahl` wird evaluiert
    -- und sein Wert zurückgegeben
    return zahl * zahl
end
-- Zahl quadrieren
print(quadrat(9)) -- `81`

Wie in Python und Ja­va­Script kann eine Funktion in Lua eine variable Anzahl von Ar­gu­men­ten ent­ge­gen­neh­men. Die Argumente werden im spe­zi­el­len Konstrukt „(...)“ ge­spei­chert. Um auf die Argumente zu­zu­grei­fen, ist es oft nützlich, diese mit dem Ausdruck „{...}“ in einer Liste zu­sam­men­zu­fas­sen. Al­ter­na­tiv kommt die „select()“-Funktion zum Einsatz, die ein Argument unter dem an­ge­ge­be­nen Index ex­tra­hiert. Die Anzahl der Argumente ermitteln wir mit dem Ausdruck „#{...}“.

-- alle Argumente einer Funktion drucken
function var_args(...)
    for index, arg    in ipairs({...}) do
        print(index, arg)
    end
end
var_args('Peter', 42, true)

Neben der variablen Anzahl von Ar­gu­men­ten erlaubt Lua auch, mehrere Werte mit einer „return“-Anweisung zu­rück­zu­ge­ben. Dies funk­tio­niert ähnlich wie in Python, jedoch ohne ex­pli­zi­ten „Tupel“-Typ. Wie in Python ist es üblich, die Rück­ga­be­wer­te beim Funk­ti­ons­auf­ruf mehreren Variablen zu­zu­wei­sen. Hier ein Beispiel:

-- Funktion mit mehreren Rückgabewerten
function erster_und_letzter(liste)
    -- erstes und letztes Element der Liste zurückgeben
    -- einzelne Rückgabewerte werden durch ein Komma `,` getrennt
    return liste[1], liste[#liste]
end
leute = {"Jim", "Jack", "John"}
-- Zuweisung der Rückgabewerte an mehrere Variablen
erster, letzter = erster_und_letzter(leute)
print("Der erste ist", erster)
print("Der letzte ist", letzter)

Wird einer der Rück­ga­be­wer­te nicht benötigt, nutzt man der gängigen Kon­ven­ti­on folgend den Un­ter­strich (_) als Platz­hal­ter, wie im folgenden Beispiel dar­ge­stellt:

function min_mittel_max(...)
    -- Anfangswerte für `min` und `max` auf erstes Argument setzen
    local min = select(1, ...)
    local max = select(1, ...)
    -- Mittelwert anfangs auf null setzen
    local mittel = 0
    -- über den Zahlen iterieren
    -- die Index-Variable benötigen wir nicht
    -- und nutzen daher `_` als Platzhalter
    for _, zahl    in ipairs({...}) do
        -- ggf. neues Minimum setzen
        if min > zahl then
            min = zahl
        end
        -- ggf. neues Maxiumum setzen
        if max < zahl then
            max = zahl
        end
        -- für den Durchschnitt Zahlen summieren
        mittel = mittel + zahl
    end
    -- Summe der Zahlen durch deren Anzahl teilen
    mittel = mittel / #{...}
    return min, mittel, max
end
-- hier benötigen wir den `mittel`-Wert nicht
-- und nutzen daher `_` als Platzhalter
min, _, max = min_mittel_max(78, 34, 91, 7, 28)
print("Minimum und Maximum der Zahlen sind", min, max)

Funk­tio­nen sind in Lua „first-class citizens“. Das heißt, sie können an Variablen gebunden werden und lassen sich damit auch als Argumente an andere Funk­tio­nen übergeben. Ferner kann eine Funktion als Rück­ga­be­wert einer Funktion dienen. Zu­sam­men­ge­nom­men er­mög­licht Lua damit funk­tio­na­le Pro­gram­mie­rung, hier dar­ge­stellt am Beispiel der berühmten „map()“-Funktion:

-- `map()`-Funktion in Lua
-- nimmt eine Funktion `f` und eine Liste als Argumente entgegen
function map(f, liste)
    -- neue Liste für Ausgabewerte anlegen
    local _liste = {}
    -- über den Elementen der Liste mit Index iterieren
    for index, wert in ipairs(liste) do
        -- Funktion `f()` auf den aktuellen Wert der Liste anwenden
        -- und den Rückgabewert in neuer Liste am selben Index speichern
        _liste[index] = f(wert)
    end
    -- neue Liste zurückgeben
    return _liste
end
-- Liste von Zahlen
zahlen = {3, 4, 5}
-- Funktion, die auf alle Elemente der Liste angewandt wird
function quadrat(zahl)
    return zahl * zahl
end
-- erzeugen der Quadrate via `map()`-Funktion
quadrate = map(quadrat, zahlen) -- `{9, 16, 25}`
-- quadrierte Zahlen ausgeben
for _, zahl in ipairs(quadrate) do
    print(zahl)
end

In der funk­tio­na­len Pro­gram­mie­rung wird oft Rekursion genutzt: Eine Funktion ruft sich selber mit ver­än­der­ten Ar­gu­men­ten immer wieder auf. Dabei müssen wir bei Lua besondere Vorsicht walten lassen. Funk­tio­nen, die rekursiv auf­ge­ru­fen werden, sollte man explizit als „local“ de­kla­rie­ren.

function f()
    -- rekursiver Aufruf
    f() -- verweist ggf. auf globale Variable `f`
end
-- stattdessen
local function f()
    -- rekursiver Aufruf
    f() -- verweist auf die umgebende Funktion
end
-- equivalent zu
local f; -- Variable `f` explizit als `local` deklarieren
f = function() -- Zuweisung der Funktion an die lokale Variable `f`
    f() -- verweist garantiert auf die umgebende Funktion
end
Zum Hauptmenü