Next: Funktionen und Variablen für Funktionsdefinitionen, Previous: Funktionen, Up: Funktionsdefinitionen [Contents][Index]

### 25.2 Makros

Funktion: buildq (L, expr)

  Die Variablen der Liste L werden in den Ausdruck expr substituiert. Die Substitution wird parallel ausgeführt. Das Ergebnis der Substitution wird vereinfacht, aber nicht ausgewertet.

  Die Elemente der Liste L sind Symbole oder Zuweisungen der Form `symbol: value`. Die Zuweisungen werden parallel ausgewertet. Der Wert einer Variablen auf der rechten Seite einer Zuweisung ist der globale Wert in dem Kontext in dem `buildq` aufgerufen wird und nicht der lokale Wert einer vorhergehenden Zuweisung. Erhält eine Variable keinen Wert, dann behält die Variable den globalen Wert.

  Dann werden die in der Liste L enthaltenen Variablen parallel in den Ausdruck expr substituiert.

  Enthält expr Ausdrücke der Form `splice(x)`, muss die Variable x eine Liste sein. Die Liste wird in den Ausdruck eingefügt. Siehe auch `splice`.

  Variablen in in dem Ausdruck expr, die nicht in L enthalten sind, werden nicht durch einen Wert ersetzt, auch wenn es eine globale Variable mit demselben Namen gibt, da der Ausdruck nicht ausgewertet wird.

  Beispiele:

  Der Variablen `a` wird der Wert zugewiesen. Die Variable `b` erhält den globalen Wert. Die Variable `c` hat keinen Wert. Das Ergebnis ist ein nicht ausgewerteter Ausdruck. Die Auswertung wird mit dem Quote-Quote-Operator `''` erzwungen.

      (%i1) (a: 17, b: 29, c: 1729)$
      (%i2) buildq ([a: x, b], a + b + c);
      (%o2)                      x + c + 29
      (%i3) ''%;
      (%o3)                       x + 1758

  `e` ist eine Liste, die einmal als Argument der Funktion `foo` vorliegt und zum anderen in die Argumentliste der Funktion `bar` eingefügt wird.

      (%i1) buildq ([e: [a, b, c]], foo (x, e, y));
      (%o1)                 foo(x, [a, b, c], y)
      (%i2) buildq ([e: [a, b, c]], bar (x, splice (e), y));
      (%o2)                  bar(x, a, b, c, y)

  Das Ergebnis wird nach der Substitution vereinfacht, ansonsten hätten die beiden folgenden Beispiele dasselbe Ergebnis.

      (%i1) buildq ([e: [a, b, c]], splice (e) + splice (e));
      (%o1)                    2 c + 2 b + 2 a
      (%i2) buildq ([e: [a, b, c]], 2 * splice (e));
      (%o2)                        2 a b c

  Die Variablen der Liste L erhalten ihren Wert parallel, ansonsten wäre das erste Ergebnis `foo(b,b)`. Substitutionen werden parallel ausgeführt. Im Gegensatz dazu werden die Substitutionen mit der Funktion `subst` nacheinander ausgeführt.

      (%i1) buildq ([a: b, b: a], foo (a, b));
      (%o1)                       foo(b, a)
      (%i2) buildq ([u: v, v: w, w: x, x: y, y: z, z: u],
                    bar (u, v, w, x, y, z));
      (%o2)                 bar(v, w, x, y, z, u)
      (%i3) subst ([u=v, v=w, w=x, x=y, y=z, z=u],
                   bar (u, v, w, x, y, z));
      (%o3)                 bar(u, u, u, u, u, u)

  Konstruktion einer Liste mit Gleichungen mit Variablen oder Ausdrücken auf der linken Seite und deren Werten auf der rechten Seite. Die Funktion `macroexpand` expandiert das Makro `show_values`.

      (%i1) show_values ([L]) ::= buildq ([L], map ("=", 'L, L))$
      (%i2) (a: 17, b: 29, c: 1729)$
      (%i3) show_values (a, b, c - a - b);
      (%o3)          [a = 17, b = 29, c - b - a = 1683]
      (%i4) macroexpand (show_values (a, b, c - a - b));
      (%o4)    map(=, '([a, b, c - b - a]), [a, b, c - b - a])

  Konstruktion einer Funktion.

      (%i1) curry (f, [a]) :=
              buildq ([f, a], lambda ([[x]], apply (f, append (a, x))))$
      (%i2) by3 : curry ("*", 3);
      (%o2)        lambda([[x]], apply(*, append([3], x)))
      (%i3) by3 (a + b);
      (%o3)                       3 (b + a)

Funktion: macroexpand (expr)

  Ist das Argument expr ein Makro, wird das Makro expandiert, ohne dass es ausgewertet wird. Ansonsten wird expr zurückgegeben.

  Ist die Expansion des Makros selbst ein Makro, wird dieses Makro wiederholt expandiert.

  `macroexpand` wertet das Argument expr nicht aus. Hat die Expansion des Makros Seiteneffekte, dann werden diese ausgeführt.

  Siehe auch `::=` und `macroexpand1`.

  Beispiele:

      (%i1) g (x) ::= x / 99;
                                          x
      (%o1)                      g(x) ::= --
                                          99
      (%i2) h (x) ::= buildq ([x], g (x - a));
      (%o2)            h(x) ::= buildq([x], g(x - a))
      (%i3) a: 1234;
      (%o3)                         1234
      (%i4) macroexpand (h (y));
                                    y - a
      (%o4)                         -----
                                     99
      (%i5) h (y);
                                  y - 1234
      (%o5)                       --------
                                     99

Funktion: macroexpand1 (expr)

  Gibt die Makro-Expansion von expr zurück, ohne das Ergebnis auszuwerten. Ist expr keine Makro-Funktion gibt `macroexpand1` das Argument expr zurück.

  `macroexpand1` wertet das Argument nicht aus. Hat die Expansion des Makros Seiteneffekte, dann werden diese ausgeführt.

  Enthält die Expansion expr wiederum Makros, werden diese im Unterschied zur Funktion `macroexpand` nicht expandiert.

  Siehe auch `::=` und `macroexpand`.

  Beispiele:

      (%i1) g (x) ::= x / 99;
                                          x
      (%o1)                      g(x) ::= --
                                          99
      (%i2) h (x) ::= buildq ([x], g (x - a))$
      (%i3) a: 1234;
      (%o3)                         1234
      (%i4) macroexpand1 (h (y));
      (%o4)                       g(y - a)
      (%i5) h (y);
                                  y - 1234
      (%o5)                       --------
                                     99

Optionsvariable: macroexpansion

  Standardwert: `false`

  `macroexpansion` kontrolliert die Expansion von Makros.

  `false`

    Die Expansion des Makros wird nicht für die aufrufende Funktion ersetzt.

  `expand`

    Wird die Makro-Funktion das erste Mal ausgewertet, wird die Expansion des Makros gespeichert. Weitere Aufrufe werten das Makro nicht erneut aus. Seiteneffekte, wie Zuweisungen an globale Variablen, werden nur bei der ersten Auswertung wirksam. Die Expansion des Makros beeinflusst nicht andere Ausdrücke, die das Makro ebenfalls aufrufen.

  `displace`

    Wird die Makro-Funktion das erste mal ausgewertet, wird die Expansion des Makros in den aufrufenden Ausdruck eingesetzt. Weitere Aufrufe werten das Makro nicht erneut aus. Seiteneffekte, wie Zuweisungen an globale Variablen, werden nur bei der ersten Auswertung wirksam. Die Expansion des Makros beeinflusst nicht andere Ausdrücke, die das Makro ebenfalls aufrufen.

  Beispiele:

  Hat `macroexpansion` den Wert `false`, wird eine Makro-Funktion jedes mal aufgerufen, wenn der aufrufende Ausdruck ausgewertet wird. Der aufrufende Ausdruck wird nicht modifiziert.

      (%i1) f (x) := h (x) / g (x);
                                        h(x)
      (%o1)                     f(x) := ----
                                        g(x)

      (%i2) g (x) ::= block (print ("x + 99 is equal to", x),
                             return (x + 99));

      (%o2) g(x) ::= block(print("x + 99 is equal to", x),
                                                        return(x + 99))
      (%i3) h (x) ::= block (print ("x - 99 is equal to", x),
                             return (x - 99));
      (%o3) h(x) ::= block(print("x - 99 is equal to", x),
                                                        return(x - 99))
      (%i4) macroexpansion: false;
      (%o4)                         false
      (%i5) f (a * b);
      x - 99 is equal to x
      x + 99 is equal to x
                                  a b - 99
      (%o5)                       --------
                                  a b + 99
      (%i6) dispfun (f);
                                        h(x)
      (%t6)                     f(x) := ----
                                        g(x)

      (%o6)                         done
      (%i7) f (a * b);
      x - 99 is equal to x
      x + 99 is equal to x
                                  a b - 99
      (%o7)                       --------
                                  a b + 99

  Hat `macroexpansion` den Wert `expand`, wird eine Makro-Funktion nur einmal aufgerufen. Der aufrufende Ausdruck wird nicht modifiziert.

      (%i1) f (x) := h (x) / g (x);
                                        h(x)
      (%o1)                     f(x) := ----
                                        g(x)
      (%i2) g (x) ::= block (print ("x + 99 is equal to", x),
                             return (x + 99));
      (%o2) g(x) ::= block(print("x + 99 is equal to", x),
                                                        return(x + 99))
      (%i3) h (x) ::= block (print ("x - 99 is equal to", x),
                             return (x - 99));
      (%o3) h(x) ::= block(print("x - 99 is equal to", x),
                                                        return(x - 99))
      (%i4) macroexpansion: expand;
      (%o4)                        expand
      (%i5) f (a * b);
      x - 99 is equal to x
      x + 99 is equal to x

                                  a b - 99
      (%o5)                       --------
                                  a b + 99

      (%i6) dispfun (f);
                                        h(x)
      (%t6)                     f(x) := ----
                                        g(x)

      (%o6)                         done
      (%i7) f (a * b);
                                  a b - 99
      (%o7)                       --------
                                  a b + 99

  Hat `macroexpansion` den Wert `displace`, wird eine Makro-Funktion nur einmal aufgerufen. Der aufrufende Ausdruck wird modifiziert.

      (%i1) f (x) := h (x) / g (x);
                                        h(x)
      (%o1)                     f(x) := ----
                                        g(x)
      (%i2) g (x) ::= block (print ("x + 99 is equal to", x),
                             return (x + 99));
      (%o2) g(x) ::= block(print("x + 99 is equal to", x),
                                                        return(x + 99))
      (%i3) h (x) ::= block (print ("x - 99 is equal to", x),
                             return (x - 99));
      (%o3) h(x) ::= block(print("x - 99 is equal to", x),
                                                        return(x - 99))
      (%i4) macroexpansion: displace;
      (%o4)                       displace
      (%i5) f (a * b);
      x - 99 is equal to x
      x + 99 is equal to x
                                  a b - 99
      (%o5)                       --------
                                  a b + 99
      (%i6) dispfun (f);
                                       x - 99
      (%t6)                    f(x) := ------
                                       x + 99

      (%o6)                         done
      (%i7) f (a * b);
                                  a b - 99
      (%o7)                       --------
                                  a b + 99

Systemvariable: macros

  Standardwert: `[]`

  Die Systemvariable `macros` ist eine Informationsliste, die die vom Nutzer mit dem Operator `::=` definierten Makros enthält. Wird das Makro mit einer der Funktionen `kill`, `remove` oder `remfunction` gelöscht, wird der Eintrag aus der Informationsliste entfernt. Siehe auch die Systemvariable `infolists`.

Funktion: splice (a)

  Die Funktion `splice` kann nur im Zusammenhang mit der Funktion `buildq` verwendet werden. Das Argument a bezeichnet eine Liste, die an Stelle von `splice(a)` in einen Ausdruck eingefügt wird. a kann nicht selbst eine Liste oder ein Ausdruck sein, der zu einer Liste auswertet.

  Beispiele:

      (%i1) buildq ([x: [1, %pi, z - y]], foo (splice (x)) / length (x));
                             foo(1, %pi, z - y)
      (%o1)                -----------------------
                           length([1, %pi, z - y])
      (%i2) buildq ([x: [1, %pi]], "/" (splice (x)));
                                      1
      (%o2)                          ---
                                     %pi
      (%i3) matchfix ("<>", "<>");
      (%o3)                          <>
      (%i4) buildq ([x: [1, %pi, z - y]], "<>" (splice (x)));
      (%o4)                   <>1, %pi, z - y<>

Next: Funktionen und Variablen für Funktionsdefinitionen, Previous: Funktionen, Up: Funktionsdefinitionen [Contents][Index]