Nächste: , Vorige:   [Inhalt][Index]

27 Programmierung


27.1 Lisp und Maxima

Lisp- und Maxima-Bezeichner

Maxima ist in Lisp programmiert. Es ist einfach, Lisp-Funktionen und Lisp-Variable in Maxima zu verwenden. Umgekehrt können Maxima-Funktionen und Maxima-Variablen in Lisp verwendet werden. Ein Lisp-Symbol, das mit einem Dollarzeichen $ beginnt, entspricht einem Maxima-Symbol ohne einem Dollarzeichen. Umgekehrt entspricht einem Maxima-Symbol, das mit einem Fragezeichen ? beginnt, ein Lisp-Symbol ohne das Fragezeichen. Zum Beispiel entspricht dem Maxima-Symbol foo das Lisp-Symbol $foo und dem Maxima-Symbol ?foo entspricht das Lisp-Symbol foo.

Speziellen Zeichen wie einem Trennstrich - oder einem Stern * in Lisp-Symbolen muss ein Backslash \ vorangestellt werden, um diese in Maxima zu verwenden. Zum Beispiel entspricht dem Lisp-Symbol *foo-bar* das Maxima-Symbol ?\*foo\-bar\*.

Im Gegensatz zu Lisp unterscheidet Maxima Groß- und Kleinschreibung. Es gibt einige Regeln, die eine Übersetzung von Namen zwischen Lisp und Maxima betreffen:

  1. Ein Lisp-Bezeichner, der nicht von senkrechten Strichen eingeschlossen ist, entspricht einem klein geschriebenen Maxima-Bezeichner. Die Schreibweise des Lisp-Bezeichners wird dabei ignoriert. Zum Beispiel entspricht den folgenden Lisp-Bezeichnern $foo, $FOO und $Foo jeweils der Maxima-Bezeichner foo.
  2. Ein Lisp-Bezeichner, der vollständig groß oder klein geschrieben ist und von senkrechten Strichen eingeschlossen wird, entspricht einem Maxima-Bezeichner in der umgekehrten Schreibweise. Ein klein geschriebener Lisp-Bezeichner wird also zu einem großgeschriebenen Maxima-Bezeichner und umgekehrt. Zum Beispiel entsprechen den Lisp-Bezeichnern |$FOO| und |$foo| die Maxima-Bezeichner foo und FOO.
  3. Ein Lisp-Bezeichner in gemischter Schreibweise, der von senkrechten Strichen eingeschlossen ist, entspricht einem Maxima-Bezeichner in der gleichen Schreibweise. Zum Beispiel entspricht dem Lisp-Bezeichner |$Foo| der Maxima-Bezeichner Foo.

Für die Syntax von Maxima-Bezeichnern siehe auch Bezeichner.

Ausführung von Lisp-Code in Maxima

Lisp-Code kann mit dem Unterbrechungskommando :lisp von einer Maxima-Kommandozeile ausgeführt werden. Siehe Debugger-Kommandos für weitere Unterbrechungskommandos und deren Beschreibung.

Beispiele:

Addiere die Werte der Maxima-Variablen x und y mit dem Lisp-Operator +.

(%i1) x:10$ y:5$
(%i3) :lisp (+ $x $y)
15

Addiere die Symbole a und b mit der Lisp-Funktion ADD. Das Ergebnis wird der Variablen $RES zugewiesen. Die Variable hat in Maxima den Namen res.

(%i3) :lisp (setq $res (add '$a '$b))
((MPLUS SIMP) $A $B)
(%i3) res;
(%o3)                         b + a

Das :lisp-Kommando ist nützlich, um zum Beispiel Lisp-Eigenschaften von Maxima-Symbolen anzuzeigen, globale Lisp-Variablen wie *PRINT-CIRCLE* zu setzen oder wie im letzten Beispiel die interne Form von Maxima-Ausdrücken anzuzeigen.

(%i4) :lisp (symbol-plist 'mabs)
(TEXSYM ((\left| ) \right| ) TEX TEX-MATCHFIX REAL-VALUED T
        MAPS-INTEGERS-TO-INTEGERS T DIMENSION DIM-MABS TRANSLATE
        #<FUNCTION (LAMBDA #) {972D045}> FLOATPROG MABSBIGFLOAT INTEGRAL
        ((X) #<FUNCTION ABS-INTEGRAL>) OPERATORS SIMPABS DISTRIBUTE_OVER
        (MLIST $MATRIX MEQUAL) NOUN $ABS REVERSEALIAS $ABS GRAD
        ((X) ((MTIMES) X ((MEXPT) ((MABS) X) -1))))

(%i4) :lisp (setq *print-circle* nil)
NIL

(%i4) 'integrate(t*sin(t), t);
                          /
                          [
(%o4)                     I t sin(t) dt
                          ]
                          /
(%i5) :lisp $%
((%INTEGRATE SIMP) ((MTIMES SIMP) $T ((%SIN SIMP) $T)) $T)

Das Kommando :lisp kann in einer Kommandozeile und in Dateien verwendet werden, die mit den Funktionen batch oder demo geladen werden. Dagegen kann das Kommando :lisp nicht in Dateien verwendet werden, die mit den Funktionen load, batchload, translate_file oder compile_file geladen werden.

Ausführung von Maxima-Code in Lisp

Das Lisp-Makro #$ erlaubt die Nutzung von Maxima-Ausdrücken in Lisp-Code. #$expr$ wird zu einem Lisp-Ausdruck expandiert, der dem Maxima-Ausdruck expr entspricht.

Beispiele:

Die beiden folgenden Beispiele zeigen die Zuweisung an eine Variable var. Im ersten Beispiel werden Lisp- und Maxima-Code gemischt. Für die Zuweisung an die Variable wird die Lisp-Funktion MSETQ aufgerufen. Das Makro #$ transformiert den Maxima Ausdruck sin(x) + a^2 in die Lisp-Form ((MPLUS SIMP) ((MEXPT SIMP) $A 2) ((%SIN SIMP) $X)). Dies entspricht dem im zweiten Beispiel gezeigten Maxima-Kommando.

(%i1) :lisp (msetq $var #$sin(x)+a^2$)
((MPLUS SIMP) ((MEXPT SIMP) $A 2) ((%SIN SIMP) $X))

(%i1) var: sin(x)+a^2;
                                     2
(%o1)                      sin(x) + a

In diesem Beispiel wird zunächst ein Maxima-Ausdruck der Variablen $VAR zugewiesen und dann mit der Lisp-Funktion DISPLA ausgegeben.

(%i1) :lisp (setq $var #$'integrate(f(x), x)$)
((%INTEGRATE SIMP) (($F SIMP) $X) $X)
(%i1) :lisp (displa $var)
/
[
I f(x) dx
]
/
NIL

Maxima-Funktionen sind keine Lisp-Funktionen. Um eine Maxima-Funktion in Lisp-Code aufzurufen, kann die Lisp-Funktion MFUNCALL aufgerufen werden.

(%i1) f(x,y) := x^2 + sin(y)$
(%i2) :lisp (mfuncall '$f '$a 10)
((MPLUS SIMP) ((%SIN SIMP) 10) ((MEXPT SIMP) $A 2))

Öffnen einer Lisp-Sitzung

Mit dem Kommando to_lisp() kann von einer Maxima-Kommandozeile eine Lisp-Sitzung geöffnet werden. Mit dem Kommando (TO-MAXIMA) wird die Lisp-Sitzung beendet und nach Maxima zurückgekehrt. Siehe auch to_lisp für ein Beispiel.

Die folgenden Lisp-Funktionen können in Maxima nicht verwendet werden:

complement, continue, /, float, functionp, array, exp, listen, signum, atan, asin, acos, asinh, acosh, atanh, tanh, cosh, sinh, tan, break, und gcd.


27.2 Einführung in die Programmierung

In Maxima können Programme geschrieben werden. Alle Maxima-Funktionen und Maxima-Variablen können in Programmen verwendet werden. Maxima hat einen Übersetzer, um Maxima-Programme in Lisp-Programme zu übersetzen, und einen Compiler, um die übersetzten Programme zu kompilieren. Siehe dazu das Kapitel Übersetzer.

Maxima-Programme bestehen aus Funktionen und Makros, die im Kapitel Funktionsdefinitionen beschrieben sind. Die Funktionen werden aus Ausdrücken der Form (expr_1, expr_2, ..., expr_n) oder block-Anweisungen zusammengesetzt. Mit der Anweisung local werden Variablen definiert, deren Werte und Eigenschaften lokal zu einem Block sind.

Konditionale Verzweigen werden mit der Anweisung if definiert und haben die Form if ... then ... else.

Maxima kennt die sehr allgemeine Anweisung for, um Schleifen zu programmieren. Schlüsselworte für die Programmierung von Schleifen sind while, unless, do sowie thru, step, in.

Mit der Sprunganweisung return kann ein Block verlassen werden und mit der Sprunganweisung go wird innerhalb eines Blockes zu eine Marke verzweigt. Nicht-lokale Rücksprünge aus Funktionen werden mit den Anweisungen catch und throw programmiert.

Die Anweisung errcatch fängt Fehler ab, so dass die Ausführung eines Programms nicht abgebrochen wird. Mit der Anweisungen error und break wird ein Programm abgebrochen. Im ersten Fall kann eine Fehlermelung ausgegeben werden und das Programm kehrt zur Maxima-Kommandozeile zurück. Mit break wird der Maxima-Debugger gestartet.

Maxima kennt die folgenden Anweisungen und Variablen um Programme zu definieren:

   backtrace    block        break
   catch        do           eval_when
   errcatch     error        error_size
   error_syms   errormsg     for
   go           if           local
   return       throw        unless
   while

27.3 Funktionen und Variablen der Programmierung

Funktion: backtrace ()
Funktion: backtrace (n)

Gibt den Aufruf-Stack der Funktion zurück, die ausgeführt wird.

Das Kommando backtrace() zeigt den gesamten Stack. backtrace(n) zeigt die letzten n Funktionen einschließlich der Funktion, die ausgeführt wird.

backtrace kann in einer Batch-Datei, die zum Beispiel mit der Funktion batch geladen wird, in einer Funktion oder von einer Kommandozeile aufgerufen werden.

Beispiele:

backtrace() gibt den gesamten Stack aus.

(%i1) h(x) := g(x/7)$
(%i2) g(x) := f(x-11)$
(%i3) f(x) := e(x^2)$
(%i4) e(x) := (backtrace(), 2*x + 13)$
(%i5) h(10);
#0: e(x=4489/49)
#1: f(x=-67/7)
#2: g(x=10/7)
#3: h(x=10)
                              9615
(%o5)                         ----
                               49

backtrace(n) gibt die letzten n Funktionen aus.

(%i1) h(x) := (backtrace(1), g(x/7))$
(%i2) g(x) := (backtrace(1), f(x-11))$
(%i3) f(x) := (backtrace(1), e(x^2))$
(%i4) e(x) := (backtrace(1), 2*x + 13)$
(%i5) h(10);
#0: h(x=10)
#0: g(x=10/7)
#0: f(x=-67/7)
#0: e(x=4489/49)
                              9615
(%o5)                         ----
                               49
Funktion: block ([v_1, …, v_m], expr_1, …, expr_n)
Funktion: block (expr_1, …, expr_n)

Mit der Anweisung block werden Ausdrücke in einer lokalen Umgebung zusammengefasst. block wertet die Argument expr_1, expr_2, …, expr_n nacheinander aus und gibt das Ergebnis des letzten ausgewerteten Ausdrucks zurück. Die Liste [v_1, ..., v_m] am Anfang der block-Anweisung bezeichnet Variablen, die innerhalb der block-Anweisung lokal sind. Alle anderen Variablen, die in einem Block verwendet werden, beziehen sich auf globale Variablen, die außerhalb des Block definiert sind. Dies kann ein weiterer Block oder die globale Maxima-Umgebung sein. block sichert die aktuellen Werte der Variablen v_1, …, v_m. Wird block verlassen, werden diese Werte wiederhergestellt.

Die Deklaration local(v_1, ..., v_m) innerhalb der block-Anweisung sichert nicht nur die Werte, sondern auch die Eigenschaften der Variablen wie sie zum Beispiel mit den Funktionen declare oder depends definiert werden. Erhalten die mit local deklarierten Variablen innerhalb der block-Anweisung Eigenschaften, wirken sich diese nur lokal aus. Beim Verlassen der block-Anweisung werden die globalen Eigenschaften wiederhergestellt. Siehe auch local.

Die block-Anweisung kann verschachtelt werden. Jeder Block kann eigene lokale Variablen definieren. Diese sind global zu jedem anderen Block der sich innerhalb des Blockes befindet. Ein Variable die nicht als lokal definiert ist, hat den globalen Wert eines umgebenden Blocks oder den Wert der globalen Maxima-Umgebung.

Der Rückgabewert eines Blocks ist der Wert des letzten Ausdrucks oder der Wert, der mit den return-Anweisung zurückgegeben wird. Mit der go-Anweisung kann innerhalb eines Blocks zu einer Marke gesprungen werden. Weiterhin kann mit der throw-Anweisung ein nicht-lokaler Rücksprung zu einer entsprechenden catch-Anweisung erfolgen.

Blöcke erscheinen typischerweise auf der rechten Seite einer Funktionsdefinitionen. Sie können aber auch an anderen Stellen verwendet werden.

Beispiel:

Das Beispiel zeigt eine einfache Implementation des Newton-Algorithmus. Der Block definiert die lokalen Variablen xn, s und numer. numer ist eine Optionsvariable, die im Block einen lokalen Wert erhält. Im Block ist das Tag loop definiert. Zu diesem Tag wird mit der Anweisung go(loop) gesprungen. Der Block und damit die Funktion wird mit der Anweisung return(xn) verlassen. Der Wert der Variablen xn ist das Ergebnis der Funktion newton.

newton(exp,var,x0,eps):=
   block([xn,s,numer],
      numer:true,
      s:diff(exp,var),
      xn:x0,
   loop,
      if abs(subst(xn,var,exp))<eps then return(xn),
      xn:xn-subst(xn,var,exp)/subst(xn,var,s),
      go(loop) )$
Funktion: break (expr_1, …, expr_n)

Wertet die Ausdrücke expr_1, …, expr_n aus, zeigt die Ergebnisse an und führt dann eine Unterbrechung aus. Mit dem Kommando exit; wird Maxima fortgesetzt. Siehe das Kapitel

Beispiel:

Der Variablen a wird der Wert 2 zugewiesen. Dann wird die Unterbrechung ausgeführt. Mit dem Kommando exit; wird Maxima fortgesetzt.

(%i1) break(a:2);
2 

Entering a Maxima break point. Type 'exit;' to resume.
_a;
2
_exit;
(%o1)                           2
Funktion: catch (expr_1, …, expr_n)

Wertet die Ausdrücke expr_1, …, expr_n nacheinander aus. Wertet irgendeiner der Ausdrücke zu throw(arg) aus, dann ist das Ergebnis der Wert von throw(arg) und es werden keine weiteren Ausdrücke ausgewertet. Diese nicht-lokale Rückgabe kehrt zu dem nächsten catch in einer beliebigen Verschachtelungstiefe zurück. Wird kein catch gefunden gibt Maxima eine Fehlermeldung aus.

Führt die Auswertung der Argumente nicht zu einem throw, dann ist die Rückgabe das Ergebnis des letzten Ausdrucks expr_n.

Beispiel:

Die Funktion g gibt eine Liste mit den Werten des Lambda-Ausdrucks zurück. Tritt ein negativer Wert auf, bricht die Funktion ab, in diesem Beispiel mit throw(-3).

(%i1) lambda ([x], if x < 0 then throw(x) else f(x))$
(%i2) g(l) := catch (map (''%, l))$
(%i3) g ([1, 2, 3, 7]);
(%o3)               [f(1), f(2), f(3), f(7)]
(%i4) g ([1, 2, -3, 7]);
(%o4)                          - 3
Spezieller Operator: do

Die do-Anweisung erlaubt die Definition von Iterationen. Aufgrund der großen Allgemeinheit der do-Anweisung folgt die Beschreibung in zwei Teilen. Zunächst werden die bekannteren Formen beschrieben, wie sie auch in anderen Programmiersprachen vorhanden sind. Dann folgen die weiteren Möglichkeiten.

Es gibt drei Varianten der do-Anweisung, die sich nur durch die Abbruchbedingung voneinander unterscheiden. Diese sind:

for variable: initial_value step increment
      thru limit do body

for variable: initial_value step increment
      while condition do body

for variable: initial_value step increment
      unless condition do body

initial_value, increment, limit und body können beliebige Ausdrücke sein. Ist das Inkrement 1, kann step entfallen.

Die Ausführung der do-Anweisung beginnt mit der Zuweisung von initial_value an die Kontrollvariable variable. Dann folgen die Schritte: (1) Hat die Kontrollvariable den Wert einer thru-Anweisung überschritten oder hat die Bedingung einer unless-Anweisung den Wert true oder hat die Bedingung einer while-Anweisung den Wert false, dann endet die Ausführung der do-Anweisung. (2) Die Ausdrücke in body werden ausgewertet. (3) Das Inkrement wird zu der Kontrollvariablen hinzuaddiert. Die Schritte (1) bis (3) werden solange ausgeführt, bis eine der Bedingungen für die Beendigung der do-Anweisung zutrifft.

Im Allgemeinen ist der thru-Test erfüllt, wenn die Kontrollvariable größer als limit ist, falls increment nicht negativ ist. Oder wenn die Kontrollvariable kleiner als limit ist, für den Fall, dass das Inkrement negativ ist. increment und limit können Ausdrücke sein, sofern die Bedingung zum Abbruch der do-Anweisung ausgewertet werden kann. Soll increment zu einem negativen Wert auswerten und kann dies jedoch bei Eintritt in die Schleife von Maxima nicht festgestellt werden, so wird das Inkrement als positiv angenommen. Dies kann dazu führen, dass die Schleife nicht korrekt ausgeführt wird.

limit, increment und die Bedingung für den Abbruch der Schleife werden für jeden Durchgang durch die Schleife ausgewertet. Ändern diese ihren Wert nicht, kann es daher effizienter sein, die Werte diese Ausdrücke vor Eintritt in die Schleife zu berechnen und in Variablen abzulegen, die anstatt der Ausdrücke in der Schleife verwendet werden.

Die do-Anweisung hat den Rückgabewert done. Um einen anderen Wert zurückzugeben, kann die return-Anweisung innerhalb von body genutzt werden. Befindet sich die do-Anweisung innerhalb eines Blockes, so wird dieser nicht mit einer return-Anweisung verlassen, die sich innerhalb der do-Anweisung befindet. Auch kann nicht mit der go-Anweisung in einen umgebenen Block gesprungen werden.

Die Kontrollvariable ist immer lokal zur do-Anweisung. Nach dem Verlassen der do-Anweisung kann auf die Kontrollvariable nicht mehr zugegriffen werden.

(%i1) for a:-3 thru 26 step 7 do display(a)$
                             a = - 3

                              a = 4

                             a = 11

                             a = 18

                             a = 25

Die Bedingung while i <= 10 ist äquivalent zu den Bedingungen unless i > 10 und thru 10 ist.

(%i1) s: 0$
(%i2) for i: 1 while i <= 10 do s: s+i;
(%o2)                         done
(%i3) s;
(%o3)                          55

Berechne die ersten acht Terme einer Taylorreihe in einer do-Schleife.

(%i1) series: 1$
(%i2) term: exp (sin (x))$
(%i3) for p: 1 unless p > 7 do
          (term: diff (term, x)/p, 
           series: series + subst (x=0, term)*x^p)$
(%i4) series;
                  7    6     5    4    2
                 x    x     x    x    x
(%o4)            -- - --- - -- - -- + -- + x + 1
                 90   240   15   8    2

In diesem Beispiel wird die negative Wurzel von 10 mit einem Newton-Raphson-Algorithmus berechnet.

(%i1) poly: 0$
(%i2) for i: 1 thru 5 do
          for j: i step -1 thru 1 do
              poly: poly + i*x^j$
(%i3) poly;
                  5      4       3       2
(%o3)          5 x  + 9 x  + 12 x  + 14 x  + 15 x
(%i4) guess: -3.0$
(%i5) for i: 1 thru 10 do
          (guess: subst (guess, x, 0.5*(x + 10/x)),
           if abs (guess^2 - 10) < 0.00005 then return (guess));
(%o5)                  - 3.162280701754386

Anstatt eines festes Inkrements mit step kann die Kontrollvariable auch mit next für jeden Schleifendurchgang berechnet werden.

(%i6) for count: 2 next 3*count thru 20 do display (count)$
                            count = 2

                            count = 6

                           count = 18

Anstatt mit der Syntax for variable: value ... kann die Kontrollvariable auch mit for variable from value ...do... initialisiert werden. Wird auch from value fortgelassen, wird die Kontrollvariable mit dem Wert 1 initialisiert.

Manchmal kann es von Interesse sein, in einer Schleife keine Kontrollvariable zu nutzen. In diesem Fall genügt es allein die Bedingung für den Abbruch der Schleife anzugeben. Im folgenden wird die Wurzel aus 5 mit dem Heron-Verfahren bestimmt.

(%i1) x: 1000$
(%i2) thru 20 do x: 0.5*(x + 5.0/x)$
(%i3) x;
(%o3)                   2.23606797749979
(%i4) sqrt(5), numer;
(%o4)                   2.23606797749979

Auch die Abbruchbedingung kann fortgelassen werden. Wird allein do body angegeben, wird die Schleife unendlich oft ausgeführt. Die Schleife kann mit der return-Anweisung verlassen werden. Das folgende Beispiel zeigt eine Implementierung des Newton-Algorithmus.

(%i1) newton (f, x):= ([y, df, dfx], df: diff (f ('x), 'x),
          do (y: ev(df), x: x - f(x)/y, 
              if abs (f (x)) < 5e-6 then return (x)))$
(%i2) sqr (x) := x^2 - 5.0$
(%i3) newton (sqr, 1000);
(%o3)                   2.236068027062195

Eine weitere Syntax ist die folgende:

for variable in list end_tests do body

Die Elemente der Liste list können beliebige Ausdrücke sein, die nacheinander der Kontrollvariablen zugewiesen werden. Die Schleife bricht ab, wenn die optionale Abbruchbedingung end_test zutrifft, wenn die Liste list keine weiteren Elemente enthält oder wenn die Schleife zum Beispiel mit der Funktion return verlassen wird.

(%i1)  for f in [log, rho, atan] do ldisp(f(1))$
(%t1)                                  0
(%t2)                                rho(1)
                                     %pi
(%t3)                                 ---
                                      4
(%i4) ev(%t3,numer);
(%o4)                             0.78539816
Funktion: eval_when (keyword, expr_1, …, expr_n)
Funktion: eval_when ([keyword_1, keyword_2, …], expr_1, …, expr_n)

Ein Ausdruck mit der Funktion eval_when wird an oberster Stelle in einer Datei definiert und erlaubt die bedingte Auswertung von Ausdrücken beim Laden, Übersetzen oder Kompilieren einer Datei. Das Argument keyword ist eines der Schlüsselworte batch, translate, compile oder loadfile. Das erste Argument kann ein einzelnes Schlüsselwort oder ein Liste mit mehreren Schlüsselworten sein. Trifft die mit dem Schlüsselwort angegebene Bedingung zu, wird eine oder mehrere der folgenden Aktionen ausgeführt:

batch

Wird die Datei mit einer der Funktionen load, batch, batchload oder demo geladen und ist batch in der Liste der Schlüsselworte enthalten, dann werden die Ausdrücke expr1, …, expr_n genau einmal beim Laden der Datei ausgewertet. Die Rückgabe der Funktion eval_when ist ein Ausdruck evaluated_when(result), wobei result das Ergebnis der Auswertung ist. Ist das Schlüsselwort batch nicht vorhanden, ist die Rückgabe das Symbol not_evaluated_when.

translate

Wird die Datei mit dem Kommando translate_file oder compile_file geladen und ist translate unter den Schlüsselworten, dann werden die Ausdrücke expr_1, …, expr_n sofort ausgewertet. Seiteneffekte wie Zuweisungen von Werten an Optionsvariablen oder Deklarationen sind für die folgende Übersetzung der Datei nach Lisp wirksam. Die Ausdrücke sind jedoch nicht Teil des übersetzten Programms.

loadfile

Wird die Datei mit dem Kommando translate_file oder dem Kommando compile_file geladen und ist loadfile unter den Schlüsselworten, dann werden die Ausdrücke expr_1, …, expr_n nach Lisp übersetzt und als Block der Form (PROGN EXPR_1 ... EXPR_N) in das Lisp Programm eingesetzt. Hier sind die Anweisungen EXPR_I die nach Lisp übersetzten Maxima-Ausdrücke expr_i.

compile

Wird die Datei mit dem Kommando translate_file oder compile_file geladen und ist compile unter den Schlüsselworten, dann werden die Ausdrücke expr_1, …, expr_n nach Lisp übersetzt und als eine Lisp-Anweisung in das Lisp-Programm eingesetzt, die die Form (EVAL-WHEN (:COMPILE-TOPLEVEL) (EXPR_1 ... EXPR_N)) hat. Das Schlüsselwort compile kann nicht mit dem Schlüsselwort loadfile in einem eval_when-Ausdruck kombiniert werden. In diesem Fall wird das Schlüsselwort compile ignoriert.

Beispiele:

Für die folgende Beispiele ist eine Datei mit den Namen eval_when.mac definiert, die verschiedene eval_when-Anweisungen enthält.

(%i1) file: file_search("eval_when.mac");
(%o1)        /home/dieter/.maxima/eval_when.mac
(%i2) printfile(file);

eval_when(batch,     print("called in mode BATCH"));
eval_when(loadfile,  print("called in mode LOADFILE"));
eval_when(compile,   print("called in mode COMPILE"));
eval_when(translate, print("called in mode TRANSLATE"));

(%o2)        /home/dieter/.maxima/eval_when.mac

Die Datei wird mit dem Kommando load geladen. Die Anweisung mit dem Schlüsselwort batch wird beim Laden einmal ausgeführt.

(%i1) file: file_search("eval_when.mac");
(%o1)        /home/dieter/.maxima/eval_when.mac
(%i2) load("file");
called in mode BATCH
(%o2)        /home/dieter/.maxima/eval_when.mac

In diesem Fall wird die Datei mit dem Befehl batch geladen. Die Anweisung mit dem Schlüsselwort batch wird einmal ausgeführt. Die anderen eval_when-Anweisungen werten jeweils zum Ergebnis not_evaluated_when aus.

(%i3) batch(file);

read and interpret file: /home/dieter/.maxima/eval_when.mac
(%i4)     eval_when(batch, print(called in mode BATCH))
called in mode BATCH 
(%o4)         evaluated_when(called in mode BATCH)
(%i5)  eval_when(loadfile, print(called in mode LOADFILE))
(%o5)                  not_evaluated_when
(%i6)   eval_when(compile, print(called in mode COMPILE))
(%o6)                  not_evaluated_when
(%i7) eval_when(translate, print(called in mode TRANSLATE))
(%o7)                  not_evaluated_when
(%o7)        /home/dieter/.maxima/eval_when.mac

Jetzt wird die Datei mit dem Kommando translate_file geladen und nach Lisp übersetzt. Der Ausdruck mit dem Schlüsselwort translate wird sofort ausgewertet. Das übersetzte Programm wird in die Ausgabedatei eval_when.LISP geschrieben. Die eval_when-Anweisung zum Schlüsselwort wird nicht ausgewertet.

(%i1) file: file_search("eval_when.mac");
(%o1)        /home/dieter/.maxima/eval_when.mac
(%i2) translate_file(file);
translator: begin translating /home/dieter/.maxima/eval_when.mac.
called in mode TRANSLATE 
(%o2) [/home/dieter/.maxima/eval_when.mac, 
/home/dieter/.maxima/eval_when.LISP, 
/home/dieter/.maxima/eval_when.UNLISP]

Dies ist der Inhalt der Ausgabedatei eval_when.LISP. Die Ausgabedatei enthält eine PROGN-Anweisung mit dem Ausdruck ($print '"called in mode LOADFILE") für den eval_when-Ausdruck zum Schlüsselwort loadfile sowie eine EVAL-WHEN-Anweisung mit dem Ausdruck ($print '"called in mode COMPILE") für den eval_when-Ausdruck mit dem Schlüsselwort compile.

;;; -*- Mode: Lisp; package:maxima; syntax:common-lisp ;Base: 10 -*- ;;;
;;; Translated on: 2011-10-02 13:35:37+02:00
;;; Maxima version: 5.25post
;;; Lisp implementation: SBCL
;;; Lisp version: 1.0.45
(in-package :maxima)

[...]

nil
(progn ($print '"called in mode LOADFILE"))
(eval-when (:compile-toplevel) ($print '"called in mode COMPILE"))
nil
Funktion: errcatch (expr_1, …, expr_n)

Wertet die Ausdrücke expr_1, …, expr_n nacheinander aus und gibt das Ergebnis des letzten Ausdrucks als eine Liste [expr_n] zurück, wenn kein Fehler bei der Auswertung auftritt. Tritt ein Fehler bei der Auswertung eines der Ausdrücke auf, ist die Rückgabe eine leere Liste [].

errcatch ist nützlich in Batch-Dateien. Mit errcatch kann ein möglicher Fehler abgefangen werden, ohne das die Verarbeitung der Batch-Datei abbricht.

Beispiele:

(%i1) errcatch(x:2,1/x);
                                1
(%o1)                          [-]
                                2
(%i2) errcatch(x:0,1/x);

Division by 0
(%o2)                          []
Funktion: error (expr_1, …, expr_n)
Systemvariable: error

Wertet die Ausdrücke expr_1, …, expr_n aus, gibt diese auf der Konsole aus und generiert einen Fehler, der zur obersten Ebene von Maxima führt oder zu dem nächsten errcatch.

Der Systemvariablen error wird eine Liste zugewiesen, die eine Beschreibung des Fehlers enthält. Das erste Element der Liste ist eine Zeichenkette und die weiteren Elemente enthalten die Argumente die keine Zeichenkette sind.

errormsg() formatiert und gibt die Fehlermeldung in error aus. Damit wird die letzte Fehlermeldung erneut ausgegeben.

Beispiel:

(%i1) f(x):= if x=0 then 
                error("Division durch", x, "ist nicht gestattet.") 
             else 1/x$
(%i2) f(0);

Division durch 0 ist nicht gestattet.
#0: f(x=0)
 -- an error. To debug this try: debugmode(true);
(%i3) errormsg();

Division durch 0 ist nicht gestattet.
(%o3)                         done
(%i4) error;
(%o4)      [Division durch ~M ist nicht gestattet., 0]
Optionsvariable: error_size

Standardwert: 10

error_size kontrolliert die Ausgabe eines Ausdrucks der zu einem Fehler geführt hat. Ist der Ausdruck größer als error_size wird der Ausdruck bei der Ausgabe einer Fehlermeldung durch ein Symbol ersetzt und dem Symbol wird der Ausdruck zugewiesen. Die Symbole werden aus der Liste error_syms ausgewählt.

Ist der Ausdruck kleiner als error_size wird dieser mit der Fehlermeldung ausgegeben.

Siehe auch error und error_syms.

Beispiel:

Die Größe des Ausdrucks U ist 24.

(%i1) U: (C^D^E + B + A)/(cos(X-1) + 1)$

(%i2) error_size: 20$

(%i3) error ("Example expression is", U);

Example expression is errexp1
 -- an error.  Quitting.  To debug this try debugmode(true);
(%i4) errexp1;
                            E
                           D
                          C   + B + A
(%o4)                    --------------
                         cos(X - 1) + 1
(%i5) error_size: 30$

(%i6) error ("Example expression is", U);

                         E
                        D
                       C   + B + A
Example expression is --------------
                      cos(X - 1) + 1
 -- an error.  Quitting.  To debug this try debugmode(true);
Optionsvariable: error_syms

Standardwert: [errexp1, errexp2, errexp3]

In Fehlermeldungen werden Ausdrücke, die größer als error_size sind, durch Symbole ersetzt, denen der Ausdruck zugewiesen wird. Die Symbole werden nacheinander der Liste error_syms entnommen.

Sind keine Symbole mehr vorhanden, werden automatisch neue Symbole mit concat('errexp, n) gebildet.

Siehe auch error und error_size.

Funktion: errormsg ()

Gibt die letzte Fehlermeldung erneut aus. Die Fehlermeldung ist in der Systemvariablen errormsg enthalten. Die Funktion errormsg formatiert diese und gibt sie aus.

Optionsvariable: errormsg

Standardwert: true

Hat die Optionsvariable errormsg den false wird die Ausgabe von Fehlermeldungen unterdrückt.

Der Optionsvariablen errormsg kann in einem Block kein lokaler Wert zugewiesen werden. Der globale Wert von errormsg ist stets präsent.

Beispiele:

(%i1) errormsg;
(%o1)                                true
(%i2) sin(a,b);
Wrong number of arguments to sin
 -- an error. To debug this try: debugmode(true);
(%i3) errormsg:false;
(%o3)                                false
(%i4) sin(a,b);

 -- an error. To debug this try: debugmode(true);

Der Optionsvariablen errormsg kann in einem Block kein lokaler Wert zugewiesen werden.

(%i1) f(bool):=block([errormsg:bool], 
                     print ("value of errormsg is",errormsg))$
(%i2) errormsg:true;
(%o2)                                true
(%i3) f(false);
value of errormsg is true 
(%o3)                                true
(%i4) errormsg:false;
(%o4)                                false
(%i5) f(true);
value of errormsg is false 
(%o5)                                false
Spezieller Operator: for

Anweisung für Interationen. Siehe die do-Anweisung für eine Beschreibung der Iterationsmöglichkeiten von Maxima.

Funktion: go (tag)

Erlaubt einen Sprung innerhalb eines Blocks zu einer Marke mit dem Namen tag. Um eine Anweisung mit einer Sprungmarke zu versehen, wird der Anweisung die Marke vorangestellt. Ein Beispiel ist:

block ([x], x:1, loop, x+1, ..., go(loop), ...)

Das Argument der Funktion go muss der Name einer Marke sein, die in demselben Block erscheint. Es ist nicht möglich in einen anderen Block zu springen.

Spezieller Operator: if

Ist die bedingte Anweisung. Verschiedene Formen einer bedingten Anweisung sind möglich.

if cond_1 then expr_1 else expr_0 wertet zu expr_1 aus, wenn die Bedingung cond_1 den Wert true hat. Ansonsten wertet der Ausdruck zu expr_0 aus.

Die zusammengesetzte bedingte Anweisung if cond_1 then expr_1 elseif cond_2 then expr_2 elseif ... else expr_0 wertet zu expr_k aus, wenn die Bedingung cond_k den Wert true hat und alle vorhergehenden Bedingungen den Wert false haben. Trifft keine der Bedingungen zu, wertet der Ausdruck zu expr_0 aus.

Fehlt die Anweisung else, wird diese zu else false angenommen. if cond_1 then expr_1 ist daher äquivalent zu if cond_1 then expr_1 else false und if cond_1 then expr_1 elseif ... elseif cond_n then expr_n ist äquivalent zu if cond_1 then expr_1 elseif ... elseif cond_n then expr_n else false.

Die Anweisungen expr_0, …, expr_n können beliebige Maxima-Ausdrücke einschließlich weiterer if-Anweisungen sein. Die Anweisungen werden nicht vereinfacht oder ausgewertet, solange die dazugehörende Bedingung nicht das Ergebnis true hat.

Die Bedingungen cond_1, …, cond_n sind Ausdrücke, die zu true oder false ausgewertet werden können. Kann eine Bedingung nicht zu true oder false ausgewertet werden, hängt die Reaktion von der Optionsvariablen prederror ab. Hat prederror den Wert true, dann meldet Maxima einen Fehler, wenn eine Bedingung nicht zu true oder false ausgewertet werden kann. Ansonsten werden Bedingungen akzeptiert, die nicht zu true oder false ausgewertet werden können und das Ergebnis ist ein bedingter Ausdruck.

Die Bedingungen können die folgenden Operatoren enthalten:

Operation              Symbol      Typ
 
less than              <           relational infix
less than              <=
  or equal to                      relational infix
equality (syntactic)   =           relational infix
negation of =          #           relational infix
equality (value)       equal       relational function
negation of equal      notequal    relational function
greater than           >=
  or equal to                      relational infix
greater than           >           relational infix
and                    and         logical infix
or                     or          logical infix
not                    not         logical prefix
Funktion: local (v_1, …, v_n)

Speichert alle Eigenschaften der Symbole v_1, …, v_n, entfernt die Eigenschaften und stellt die abgespeicherten Eigenschaften nach dem Austritt aus einem Block oder einem zusammengesetzten Ausdruck in dem local auftritt wieder her.

Einige Deklarationen sind als Eigenschaft eines Symbols implementiert. Dazu gehören Deklarationen mit :=, array, dependencies, atvalue, matchdeclare, atomgrad, constant, nonscalar oder assume. Der Effekt von local ist, dass solche Deklarationen nur lokal in dem Block wirksam sind.

local kann nur in block-Anweisungen oder in einer Funktionsdefinition oder in einem Lambda-Ausdruck verwendet werden. Weiterhin darf local jeweils nur einmal auftreten.

local wertet die Argumente aus. local hat die Rückgabe done.

Beispiel:

Eine lokale Funktionsdefinition.

(%i1) foo (x) := 1 - x;
(%o1)                    foo(x) := 1 - x
(%i2) foo (100);
(%o2)                         - 99
(%i3) block (local (foo), foo (x) := 2 * x, foo (100));
(%o3)                          200
(%i4) foo (100);
(%o4)                         - 99
Funktion: return (value)

Die return-Anweisung wird in einem Block verwendet, um den Block mit dem Ergebnis value zu verlassen. Siehe block für mehr Informationen.

Funktion: throw (expr)

Wertet den Ausdruck expr aus und generiert eine Ausnahme mit dem Ergebnis der Auswertung, die von der letzten catch-Anweisung behandelt wird.

Spezieller Operator: while
Spezieller Operator: unless

Siehe den Operator do.


Nächste: , Vorige:   [Inhalt][Index]