Inhaltsverzeichnis

Funktionen

Durch Funktionen können Programme in kleine, wiederverwertbare Teile partitioniert werden. Diese Teil-Programme sind normalerweise in sich geschlossen und erfüllen einen bestimmten Aspekt des gesamten Programms.

Für einen Drucker beispielsweise könnte man folgende Funktionen definieren: „Hole Papier“, „Bewege Papier“, „Leite Tinte zum Druckkopf“, „Bewege Druckkopf“, „Verarbeite Bilddaten“. Jede einzelne dieser Funktionen würde für sich genommen kein Bild ausdrucken können. Wenn alle diese Funktionen jedoch korrekt benutzt werden und zusammenarbeiten können, kann erfolgreich gedruckt werden.
In diesem Beispiel dienen Funktionen also dazu

  1. Den Vorgang „Drucken“ in kleine logische Prozesse zu teilen
  2. Einem Prozess einen bestimmten Namen zu geben
  3. Jeden Prozess unabhängig von den anderen benutzen zu können
  4. Jeden Prozess immer genau gleich ablaufen zu lassen

Jede Funktion kann außerdem Eingabewerte (Parameter) entgegen nehmen. Das bedeutet, dass sich die gleiche Funktion basierend auf sich verändernden Eingabewerten unterschiedlich verhält. Die Druckerfunktion „Bewege Druckkopf“ könnte beispielsweise Parameter für die Koordinaten erhalten, an die sich der Druckkopf bewegen soll.

Funktionen werden mit dem Schlüsselwort function eingeleitet und deren Ende mit end deklariert. Die Namen der Parameter werden in Klammern hinter function angegeben. Innerhalb der Funktion können die Parameter unter dem gegebenen Namen benutzt werden. Alles Weitere folgt genau den Regeln der Definition von Variablen. Dazu zählen auch die Vorgaben, welche Namen für Funktionen erlaubt sind.

-- Definiere eine "Ausgangsposition" für den Druckkopf
PrintheadPositionX = 0
PrintheadPositionY = 0
 
-- Für die Parameter wählen wir in unseren Beispiel immer Namen, die mit einem Unterstrich
-- beginnen. Dadurch ist im Code immer sofort ersichtlich, bei welchen Variablen es sich um
-- Parameter handelt
MovePrinthead = function(_PositionX, _PositionY)
    PrintheadPositionX = _PositionX
    PrintheadPositionY = _PositionY
end

Falls du schon einmal mit anderen Programmiersprachen gearbeitet hast, ist diese Schreibweise möglicherweise ungewohnt. Lua bietet daher auch eine alternative Schreibweise an, die genau die gleiche Funktion definiert:

-- Dieser Code ist nur eine andere Schreibweise für das Beispiel oben
PrintheadPositionX = 0
PrintheadPositionY = 0
 
-- Das Schlüsselwort function steht nun vorne, die Parameter in Klammern hinter dem 
-- Funktionsnamen
function MovePrinthead(_PositionX, _PositionY)
    PrintheadPositionX = _PositionX
    PrintheadPositionY = _PositionY
end

Die Funktion MovePrinthead wird folgendermaßen aufgerufen:

-- Bewege Druckkopf an Position X=100, Y=200
MovePrinthead(100, 200)

Im Folgenden wollen wir nun einige Beispiele geben und weitere Anwendungsfälle von Funktionen betrachten.


Hinweis: Unsere Beispiele in diesem und den folgenden Kapiteln können besser nachvollzogen werden, wenn man die Programmzeilen nebenbei ausprobieren kann. Dazu kann man diese Webseite hier verwenden:

https://www.lua.org/demo.html

Um dabei bei der Ausgabe ein Ergebnis zu sehen, kann man die Funktion print verwenden. Will man beispielsweise die Variable PrintheadPositionX ansehen, kann man

MovePrinthead(100, 200)
print(PrintheadPositionX)

schreiben. Wenn die Variable einen anderen Namen hat, muss man diesen dementsprechend austauschen.


Funktionen mit Rückgabewert

Es gibt noch eine andere „Art“ von Funktionen. Im Fall oben haben wir die Funktion, die den Druckkopf steuert, aufgerufen und die Funktion hat Veränderungen im Drucker verursacht (ein sogenannter Seiteneffekt).
Alternativ dazu gibt es auch Funktionen, die einen Wert berechnen sollen und diesen in eine Variable zurückgeben. Dazu wird das Schlüsselwort return verwendet. Als einfaches Beispiel berechnen wir hier die Quadratwurzel einer Zahl und speichern diese in einer Variable:

Number1 = 64
 
function Sqrt(_X)
    return _X^0.5
end
 
Result = Sqrt(Number1)

Beachte hier wieder die Reihenfolge, in der die Zuweisung Result geschieht: Zuerst wird die rechte Seite Sqrt(Number1) ausgewertet. Das bedeutet, die Funktion Sqrt wird mit dem Parameter Number1 aufgerufen. Die Funktion gibt ihr Ergebnis mit return zurück. Dieses wird dann in Result abgespeichert.

Eine Funktion, die einen Rückgabewert ausgibt, ist nicht auf ein einziges return beschränkt. Wir bauen die Funktion, die das Minimum aus drei verschiedenen Zahlen berechnet (Verzweigungen), in eine Funktion mit Rückgabewert um:

function MinOfThree(_Number1, _Number2, _Number3)
    if _Number1 < _Number2 then
        if _Number1 < _Number3 then
            return _Number1
        else
            return _Number3
        end
    else
        if _Number2 < _Number3 then
            return _Number2
        else
            return _Number3
        end
    end
end
 
Minimum = MinOfThree(3, 7, 1) -- 1

Achtung: Wenn man mit return einen Ausgabewert zurückgibt, können danach keine weiteren Instruktionen folgen, da die Funktion bei return immer zuende ist. Jede weitere Instruktion darunter wird zu einem Syntaxfehler führen!


Funktionen ohne Parameter

Natürlich braucht nicht jede Funktion Parameter. Beispielsweise könnte es eine Funktion geben, die unseren Druckkopf von oben auf seine Ausgangsposition zurücksetzt. Die würde dann so aussehen:

function ResetPrinthead()
    PrintheadPositionX = 0
    PrintheadPositionY = 0
end
 
-- Beachte beim Aufruf, dass auch ohne Parameter die Klammern dahinter gebraucht werden!
ResetPrinthead()

Interaktion mehrerer Funktionen

Um ein etwas komplexeres Beispiel zu geben, wollen wir mehrere Funktionen verwenden, um die Euklidische Distanz in zwei Dimensionen zu berechnen. Dadurch wird anschaulich, wie Funktionen untereinander interagieren können.

function SquaredDifference(_X, _Y)
    return (_X-_Y)^2
end
 
function Sqrt(_X)
    return _X^0.5
end
 
function EuclideanDistance(_X1, _Y1, _X2, _Y2)
    Difference1 = SquaredDifference(_X1, _X2)
    Difference2 = SquaredDifference(_Y1, _Y2)
    return Sqrt(Difference1 + Difference2)
end
 
Distance = EuclideanDistance(2, 4, 5, 8) -- 5

Zum besseren Verständnis von Funktionen kann es helfen, dieses Beispiel Schritt für Schritt durchzurechnen und sich davon zu überzeugen, dass tatsächlich die gewünschte Funktion berechnet wird. In welcher Reihenfolge werden die einzelnen Rechenschritte vollzogen?


Das nächste Kapitel beschäftigt sich mit der Unterscheidung zwischen lokalen und globalen Variablen.

Voriges Kapitel: Verzweigungen
Nächstes Kapitel: Lokale und Globale Variablen
Zurück nach oben