====== 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
- Den Vorgang "Drucken" in kleine logische Prozesse zu teilen
- Einem Prozess einen bestimmten Namen zu geben
- Jeden Prozess unabhängig von den anderen benutzen zu können
- 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 [[ scripting:tutorials:level1:variables | 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 ([[ scripting:tutorials:level1:branches |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 [[ https://de.wikipedia.org/wiki/Euklidischer_Abstand | 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.
[[ scripting:tutorials:level1:branches | Voriges Kapitel: Verzweigungen ]]\\
[[ scripting:tutorials:level1:variable_scope | Nächstes Kapitel: Lokale und Globale Variablen ]]\\
[[ scripting:tutorials:level1:functions_blocks | Zurück nach oben ]]