Funktionsargumente:
Man kann beim Aufruf einer Funktion Werte mitgeben.
Das ist dann sinnvoll, wenn man mit ein und derselben Funktion verschiedene Dinge tun möchte. Wenn also beispielsweise eine Funktion auf einer bestimmten Tafel mal diese, mal jene Texte anzeigen soll.
Dazu schreibt man beim Aufruf der Funktion das in die Klammern, was man in diesem Moment benutzen möchte.
Also zum Beispiel Anzeige_1_Bhnstg_4("ICE", "627", "Hamburg", "13:28")
Die Funktionsdefinition bekommt in den Klammern passende Platzhalter:
function Anzeige_Kln_Bhnstg_4(Typ, Nummer, Ziel, Zeit)
Und dann verwendet man diese Platzhalter in der Funktion dort, wo man die mitgelieferten Werten nutzen möchte. Also zum Beispiel so:
function Anzeige_Kln_Bhnstg_4(Typ, Nummer, Ziel, Zeit)
EEPStructureSetTextureText("#123", 1, Typ)
EEPStructureSetTextureText("#123", 2, Typ)
EEPStructureSetTextureText("#123", 3, Nummer)
EEPStructureSetTextureText("#123", 4, Nummer)
EEPStructureSetTextureText("#123", 5, Ziel)
EEPStructureSetTextureText("#123", 6, Ziel)
EEPStructureSetTextureText("#123", 7, Zeit)
EEPStructureSetTextureText("#123", 8, Zeit)
end
Diese Platzhalter verhalten sich wie Variablen, gelten aber nur innerhalb dieser Funktion.
Man sagt: Sie haben nur lokale Gültigkeit.
Deshalb kann ich auch für eine andere Anzeige dieselben Namen verwenden, ohne dass es zu Verwechslungen kommt:
function Anzeige_Hnvr_Bhnstg_2(Typ, Nummer, Ziel, Zeit)
Ich weiß, welcher Text zu welcher Anzeigetafel gehört, weil er im entsprechenden Funktionsaufruf steht. Und Lua weiß es ebenfalls, weil die Argumente nur innerhalb der Funktion existieren. Anschließend werden sie sofort wieder vergessen.
Wenn ich mit Anzeige_Hnvr_Bhnstg_2("RE", "11", "Herrhausen", "14:05") dem Anzeiger in Hannover einen neuen Text schicke, dann bleibt der Text in Köln unverändert. Das macht den Umgang mit den Namen der Variablen einfach. Ich benötige keine kryptischen Kürzel, die für jeden Bahnsteig individuell etwas anders lauten müssen. Ich brauche auch nicht unendlich viele ähnlich aussehende Namen für die ganzen Variablen. Ich kann stattdessen einfache und gut lesbare Namen wählen.
Argumente kann man bei Funktionsdefinition und -aufruf auch untereinander schreiben:
Wahlweise mit oder ohne Einrückungen. Ganz nach persönlichem Geschmack.
Das erhöht die Lesbarkeit enorm, wenn man ein ganzes Dutzend Werte übergeben möchte. Es ist viel ratsamer als eine einzelne Zeile mit einer Länge von weit über 200 Zeichen!
Wenn man die gewünschten Inhalte direkt als Argumente in den Funktionsaufruf schreibt, dann erübrigt sich damit das Anlegen zusätzlicher Variablen für die Textbausteine, die man dann als Argumente in den Funktionsaufruf schreibt.
Der folgende Ansatz ist nicht nur unleserlich, sondern auch riskant, weil er viel zu viele Möglichkeiten für Schreibfehler enthält, die später schwer zu finden sind:
function Anzeige_Kln_Bhnstg_4(Typ_Kln_Bhnstg_4, Nummer_Kln_Bhnstg_4, Ziel_Kln_Bhnstg_4, Zeit_Kln_Bhnstg_4)
-- Darstellung der Texte
end
Typ_Kln_Bhnstg_4 = "ICE"
Nummer_Kln_Bhnstg_4 = "627"
Ziel_Kln_Bhnstg_4 = "Hamburg"
Zeit_Kln_Bhnstg_4 = "13:28"
Anzeige_1_Bhnstg_4(Typ_Kln_Bhnstg_4, Nummer_Kln_Bhnstg_4, Ziel_Kln_Bhnstg_4, Zeit_Kln_Bhnstg_4)
Und das Beispiel enthält noch einen weiteren, eklatanten Fehler.
Es vermischt globale und lokale Variablen kunterbunt.
Das ist nicht anfängerfreundlich, sondern ein Anfängerfehler!
Bitte nicht nachmachen!
- Die Variable Typ_Kln_Bhnstg_4 in Zeile 5 ist eine globale Variable.
- Beim Aufruf in Zeile 10 wird der Inhalt dieser globalen Variable übergeben.
- Die Funktionsdefinition in Zeile 1 überträgt den Wert in eine neue, lokale Variable.
- Diese lokale Variable hat denselben Namen Typ_Kln_Bhnstg_4
Daher steht die globale Variable innerhalb dieser Funktion nicht zur Verfügung.
Es bringt keinerlei Gewinn, die Texte zuerst globalen Variablen zuzuordnen und dann diese Variablen statt der Texte als Argumente mitzugeben.
(Es sei denn, dass man irrtümlich der Meinung ist, man könne die einzelnen Elemente nicht untereinander schreiben.)
Das Durcheinander von globalen und lokalen Variablen gleichen Namens führt zu einer ganzen Reihe von Missverständnissen und Fehlverhalten.
Und am Ende zu lustigen Behauptungen wie:
'bei return müssen Variablen in Klammern stehen, wenn sie Strings enthalten.'
Diese Aussage ist falsch.
Die Unterscheidung von globalen und lokalen Variablen ist für einen Anfänger gewiss nicht leicht. Aber umso wichtiger ist dann, dass man in Beispiel-Skripten für Anfänger sehr genau auf den richtigen Einsatz von globalen und lokalen Variablen achtet.
return-Werte:
Wenn eine Funktion bestimmte Werte liefern soll, dann kann sie diese Werte mit return zurück geben.
Aber was bedeutet "zurück"? Wohin "zurück"?
Dorthin, wo die Funktion aufgerufen wurde. Die Werte stehen dann an Stelle des Funktionsaufrufs. Genau so, als hätte man sie dort direkt hingeschrieben.
Die folgende Funktion bildet das Quadrat einer Zahl:
Ich darf das a innerhalb der Funktion ändern, weil es eine lokale Variable ist. Sobald die Funktion ihre Arbeit erledigt hat, wird a sowieso gelöscht.
Jetzt rufe ich die Funktion mit einer Zahl als Argument auf:
Quadrat(2)
Dann steht an genau dieser Stelle im Code eine 4 (das Quadrat von 2)
Aber wenn ich in meinem Programm einfach irgendwo eine 4 hinschreibe, dann nützt die mir nichts. Ich muss damit etwas tun.
Ich kann sie beispielsweise in einer neuen Variable speichern:
x = Quadrat(2)
ist dasselbe wie
x = 4
Oder ich kann den Wert ausgeben
print(Quadrat(2))
Das ist dann dasselbe wie print(4)
Ich kann die Funktion auch als Wert einsetzen:
EEPSetSignal(1, Quadrat(2))
Das setzt Signal 1 auf Stellung 4
Ebenso kann ich eine Funktion schreiben, die durch einen Zug ausgelöst wird und dann ein paar Texte zurückgibt:
Dann muss ich dort, wo diese Funktion aufgerufen wird, entsprechend viele Platzhalter bereithalten, um die Werte alle aufzunehmen:
a, b, c, d = ICE_662()
Das Prinzip ist von vielen EEP Funktionen bekannt:
ok, Geschwindigkeit = EEPGetTrainSpeed( "#VT98;001" )
oder
ok, Pos_X, Pos_Y, Pos_Z = EEPStructureGetPosition("#1")
Schlusswort:
Das ist alles immer noch "von hinten durch die Brust ins Auge" programmiert und nicht wirklich vernünftig.
Wenn man beim Beschriften von ZZA auf Tabellen verzichtet, dann bereitet man sich damit - auch als Anfänger - mehr Probleme, als man umgeht!
Dieser kleine Aufsatz hatte nicht das Ziel, den richtigen Weg aufzuzeigen. Vielmehr lag mir sehr dran, mit ein paar Missverständnissen aufzuräumen. Deshalb bin ich sehr nah am Original geblieben. Das fiel mir schwer, weil die ganze Struktur unklug und fehlerträchtig ist. Aber ich wollte mich unbedingt darauf konzentrieren, ein paar Falschaussagen richtig zu stellen.
Viele Grüße
Götz