Anonyme Makros
Ein anonymes Makro besteht, ebenso wie ein benanntes Makro, im Wesentlichen aus Formeltext und einer Parameterliste. Sie machen also eine Kombination von Funktionen und Makros in Form einer neuen Funktion verfügbar.
Daneben haben anonyme Makros aber weitere Eigenschaften, die über die Möglichkeiten von benannten Makros hinausgehen:
- Sie besitzen implizite Parameter.
- Sie haben einen inneren Zustand. Wird ein anonymes Makro mehrfach ausgewertet (z. B. innerhalb der Funktionen Map und MapZ), bleibt dieser innere Zustand von Auswertung zu Auswertung erhalten.
Syntax anonymer Makros
Ein anonymes Makro wird geschrieben als Raute "#", gefolgt von einer Variablenliste in eckigen Klammern, gefolgt von einem Ausdruck in runden Klammern. Dieser Ausdruck kann selbst wiederum eine Sequenz von Zuweisungen, gefolgt von einem Ergebnisterm sein:
- #[](object) ist dasselbe wie #Object, also eine Funktion, die das Eingabeobjekt selbst liefert.
- #[$y](Plus[$y]) oder #[$y](object+$y) ist dasselbe wie #Plus, d. h. die Additionsfunktion.
- #[$y]((object+$y)/2) ist eine Mittelwertsfunktion.
- #[$y]($summe:=object+$y; $summe/2) ist dieselbe Mittelwertsfunktion, in diesem Fall wurde aber eine Hilfsvariable verwendet.
Implizite Parameter
Im Unterschied zu benannten Makros können anonyme Makros Werte aufnehmen und verwenden, die in ihrem Definitionskontext gegeben sind – unabhängig davon, wann, wo und von was sie ausgewertet werden.
So kann einerseits die Mehrfachbewertung derselben Formel vermieden werden. Andererseits können Werte, die sich aus äußeren Formelparametern ableiten, in Funktionen eingebracht werden. Beispiel:
$gewicht:=2/($Zeitraum+1);
#[](object+$gewicht).Map[$liste]
- $liste sei dabei eine beliebige Liste von Zahlen.
- Bei der Auswertung wird das anonyme Makro #[](object+$gewicht) auf jedes Element von $liste Die so erzeugten Ergebnisse werden gesammelt und in einer Liste von Zahlen zusammengestellt.
- Die Funktion #[](object+$gewicht) addiert auf jede Zahl den Wert $gewicht. Obwohl der Wert von $gewicht in die Berechnung eingeht, ist die Funktion einstellig, d. h., sie benötigt nur eine Eingabe und keine sonstigen Parameter (die sonst die Funktion Map zur Verfügung stellen müsste). Welchen Wert die Variable $gewicht annimmt, entscheidet der Definitionskontext, also die Stelle, an der die Rautendefinition steht (und nicht der Aufrufkontext, also die Stelle an der im Beispiel Map angewendet wird). Beispiel:
$gewicht:=2/($Zeitraum+1);
$funktion:=#[](object+$gewicht);
$gewicht:=0;
$funktion.Map[$liste]
$gewicht:=2/($Zeitraum+1);
$funktion:=#[](object+$gewicht);
$gewicht:=0;
$funktion.Map[$liste]
Das Ergebnis ist hier dasselbe wie oben, obwohl der Wert der Variable $gewicht bei der Makroanwendung ein anderer ist, nämlich 0. Auch wenn das Funktionsobjekt z. B. an ein beliebiges benanntes Makro XX übergeben würde, das die Funktion z. B. durch Map schließlich auswertet, bleibt die Funktion unberührt von etwaigen Variablen, die ebenfalls $gewicht heißen und in der Makrodefinition von XX vorkommen.
Innerer Zustand von anonymen Makros
Innerhalb von Funktionen, die ein Funktionsobjekt mehrfach auswerten (z. B. Map, Fold, MapZ), bleiben die Variablenbelegungen von Auswertung zu Auswertung erhalten. Dies kann man nutzen, um in einer Auswertungssequenz Hilfswerte mitzuführen, die sich aus den Ergebnissen und Hilfswerten der vorangegangenen Makroanwendung ergeben.
Ein Beispiel dafür ist die Berechnung des exponentiellen Durchschnitts oder des Indikators Parabolic SAR.
Das Prinzip lässt sich an einem einfachen Beispiel verdeutlichen: Die Reihe der Fibonacci-Zahlen 1, 1, 2, 3, 5, 8, 13,... ergibt sich dadurch, dass (mit Ausnahme der ersten beiden Zahlen) jeweils die letzte und die vorletzte Zahl in der Liste addiert werden.
Die folgende Formel berechnet eine Liste von $N Fibonacci-Zahlen:
$n1:=0;
$n2:=1;
$liste:=MakeList($N);
#[]($n3:=$n1+$n2;
$n4:=$n1;
$n1:=$n2;
$n2:=$n3;
$n4).Map[$liste]
$liste wird hier als $N-elementige Liste generiert. Deren Werte sind jedoch ohne Bedeutung, da sie nicht in die Berechnung eingehen.
Das anonyme Makro enthält in den Variablen $n1 und $n2 jeweils die nächsten beiden Fibonacci-Zahlen. Bei jeder Auswertung durch Map wird die nächste Fibonacci-Zahl berechnet. Danach werden die Inhalte der Variablen entsprechend verschoben. Die Funktion liefert schließlich den alten Inhalt von $n1, also die nächste Zahl.