Hallo zusammen,
viele meiner Funktionen haben folgenden generellen Aufbau:
procedure irgendwas(r, fg, bg, s)
# Setzen von Defaults
/r := "r_message"
/fg := "black"
/bg := "white"
# Sichern von Einstellungen
altfg := Fg()
altbg := Bg()
altfont := Font()
altline := WAttrib("linewidth")
# Setzen neuer Einstellungen für diese Funktion
Fg(Setzen einer neuen Vordergrundfarbe)
Bg(Setzen einer neuen Hintergrundfarbe)
Font(Setzen eines Zeichensatzes, Größe, Stil)
# Aktion
...
...
# Rückgängig machen
Fg(altfg)
Bg(altbg)
Font(altfont)
# Ergebnis
return ...
end
Display More
Bei der Benennung der Argumente orientiere ich mich an den üblichen Icon-Vorgaben des Datentyps bzw. der Bedeutung als Argument der entsprechenden Funktion.
Die obige Struktur hat den Vorteil, dass man sich auf das Wesentliche - das Programmieren der eigentlichen Aktion konzentrieren kann. Der Rest macht man irgendwie wie im Tran.
Der Nachteil ist, dass man sich einen Wolf sucht, wenn man mal vergessen hat, z.B. den Zeichensatz für einen Alarm oder eine Systemmeldung zurückzusetzen, und alle weiteren Ausgaben auf der GUI in einem unpassenden Stil erfolgen.
Viel einfacher geht das bei Verwendung eines Stapelspeichers STACK, der mit STACK := [] oder STACK := list() angelegt wurde.
Eine Funktion sieht dann z.B. so aus:
procedure irgendwas(r, fg, bg, s)
# Defaults
/r := "r_message"
/fg := "black"
/bg := "white"
# Einstellungen sichern
put(STACK, Font(), Fg(), Bg())
# Funktionsspezifische Einstellungen
Fg(fg); Bg(bg); Font("sans,20,bold")
# Aktion
...
...
# Frühere Einstellungen zurückholen
every i := 1 to *STACK do i(Bg, Fg, Font)(pull(STACK))
end
Display More
Code-Deutung:
Die Zeile put(STACK, Font(), Fg(), Bg()) speichert den vorher verwendeten Zeichensatz, Vordergrundfarbe, Hintergrundfarbe auf diesen Stapelspeicher STACK.
STACK[1] enthält den Zeichensatz, STACK[2] die Vordergrundfarbe etc.
Die Zeile every i := 1 to *STACK do i(Bg, Fg, Font)(pull(STACK)) macht das dann wieder rückgängig. Hier habe ich die Funktion pull() verwendet, die - beginnend mit dem zuletzt mit put()auf den Stapel gebrachten Eintrag - den Stapel abräumt. Prinzipiell wären auch die anderen beiden Funktionen get() und pop() möglich gewesen. Dann müsste aber entweder in put() oder in der unteren Funktion die Reihenfolge der Parameter geändert werden, um FIFO, FILO / LIFO abzubilden.
Was hier mit i(...)(...) sehr strange aussieht, nennt sich in Icon "mutual evaluation". Damit ist eine extreme Einsparung an Code verbunden.
Ganz allgemein besteht dies aus einem Ausdruck, der ein ganzzahliges Ergebnis liefert, einer in Klammern stehenden Auflistung an "Angeboten", was getan werden könnte (also weitere Ausdrücke, Funktionen oder Variablen) und - sollten leere Funktionsnamen aufgeführt sein - dann folgen deren Parameter in einem weiteren Klammerpaar.
Bei dem i ist das leicht durchschaubar, da dies die Schleifenvariable ist, die von 1 bis 3 laufen soll.
Dieses ganzzahlige Ergebnis bildet nicht den Funktionsnamen sondern den Index, unter dem aus der nachfolgenden Aufzählung etwas ausgewählt werden soll. Bei i = 1 wird also der erste Eintrag herangezogen, also Bg. Hier könnte ein weiterer auswertbarer Ausdruck stehen, eine Variable, eine Funktion oder was auch immer. Hier steht also Bg, was eigentlich die Funktion für das Setzen der Hintergrundfarbe für kommende Zeichenfunktionen darstellt. Wenn es sich um eine Funktion handeln sollte, müssen danach auch Parameter in Klammern () angeboten werden. OK - Klammern folgen da auch noch. Die Argumente werden vom zuvor beschriebenen Stack geholt. Es handelt sich also tatsächlich um die Abwicklung der Icon-Funktion Bg().
Bei i = 2 wird Analoges für den zweiten Index, also Fg und bei i = 3 für den drittem Index Font() durchgeführt.
Am Ende ist der Stapel leer, egal, ob man ausreichend Funktionen bereitgestellt hat oder nicht und die betrachteten Einstellungen sind wieder so wie vorher.
Ich mag "mutual evaluation", weil hier in einer Zeile stehen kann, was sonst in einer Fallunterscheidung geklärt werden muss.
Beste Grüße
Andreas