[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

3. Erste Makros und Hilfsfunktionen


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

3.1 Makros

In diesem Kapitel werden erste Makros eingeführt, die sehr früh definiert werden müssen, da diese an vielen Stellen im Quellcode eingesetzt werden. Die Makros werden in der Datei mmacro.lisp definiert, die als eine der ersten Dateien von Lisp geladen wird.

Folgende Makros werden in diesem Kapitel beschrieben:

   ncons        float      while
   defun-prop   defmspec   defmvar
   errset

Weiterhin werden die folgenden globalen Variablen definiert:

   *variable-initial-values*
   *errset*

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

3.1.1 Allgemeine Makros

Makro: ncons x

Das Makro ncons macht das Argument x zum einzigen Element einer Liste.

Beispiel:

* (ncons 'a)
(A)

Quelltext:

(defmacro ncons (x)
  `(cons ,x nil))

Makro: float x &optional (y 1d0)

Das Makro float überschreibt die entsprechende Lisp-Funktion, so dass eine Zahl standardmäßig zu einer Gleitkommazahl mit doppelter Genauigkeit konvertiert wird. Zusätzlich wird in kMaxima die globale Lisp-Variable *read-default-float-format* auf den Wert double-float gesetzt.

Beispiel:

* (type-of (float 1))
DOUBLE-FLOAT

Quelltext:

(defmacro float (x &optional (y 1d0))
  `(cl:float ,x ,y))

Makro: while condition &rest body

Das Makro implementiert eine while-Schleife.

Quelltext:

(defmacro while (condition &rest body)
  `(do ()
       ((not ,condition))
     ,@body))

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

3.1.2 Die Makros defun-prop und defmspec

Makro: defun-prop f arg &body body

Das Makro defun-prop generiert den Code, um die Definition body einer Funktion auf der Eigenschaftsliste eines Symbols abzulegen. Das Argument f ist eine Liste mit zwei Elementen. Das erste Element ist ein Symbol, das die zu definierende Funktion bezeichnet. Das zweite Element ist ein Symbol, das den Indikator bezeichnet, zu dem die Definition der Funktion auf der Eigenschaftsliste abgelegt wird. Das Argument arg ist eine Liste mit den Argumenten der Funktionsdefinition. Die Rückgabe ist ein Ausdruck, der die Funktionsdefinition body mit den Argumenten arg zu einem Symbol auf der Eigenschaftsliste ablegt.

Siehe auch das Makro defmspec, mit dem kMaxima-Spezialformen definiert werden. Weiterhin werden vom Parser mit den Makros def-led-fun und def-nud-fun Funktionen definiert, die die led- und nud-Funktionen auf der Eigenschaftsliste eines Operators ablegen.

Beispiel:

Das Beispiel zeigt die Definition und die Anwendung einer Funktion f. Die Funktion hat die Argumente x und y. Die Definition der Funktion wird zum Indikator func auf der Eigenschaftsliste abgelegt.

* (macroexpand-1 '(defun-prop (f func) (x y) (+ x y)))
(SETF (GET 'F 'FUNC) #'(LAMBDA (X Y) (+ X Y)))
T
* (defun-prop (f func) (x y) (+ x y))
#<FUNCTION (LAMBDA (X Y)) {B595DBD}>
* (apply (get 'f 'func) '(2 3))
5

Quelltext:

(defmacro defun-prop (f arg &body body)
  `(setf (get ',(first f) ',(second f)) #'(lambda ,arg ,@body)))

Makro: defmspec func arg &body body

Das Makro defmspec legt die Definition body einer Funktion, die die Argumente arg hat, zum Indikator mspec auf der Eigenschaftsliste des Symbols func ab. Dazu generiert das Makro einen Ausdruck mit dem Makro defun-prop. Das Argument func ist ein Symbol das die zu definierende Funktion bezeichnet.

Mit dem Makro defmspec werden Nutzerfunktionen definiert, die ihre Argumente nicht auswerten und auch als Spezialformen bezeichnet werden. Der Evaluator meval1 erkennt Symbole, die eine Spezialform repräsentieren und wendet die Funktion an, die auf der Eigenschaftsliste abgelegt ist. Beispiele für Spezialformen sind die Funktionen $alias und $reset.

Beispiel:

* (macroexpand-1 '(defmspec f(x y) (+ x y)))
(PROGN
 (DEFUN-PROP (F MSPEC)
     (X Y)
   (+ X Y)))
T
* (defmspec f(x y) (+ x y))
#<FUNCTION (LAMBDA (X Y)) {AF8A7BD}>
* (symbol-plist 'f)
(MSPEC #<FUNCTION (LAMBDA #) {AF8A7BD}>)

Bemerkung:

Im Original Maxima wird aus historischen Gründen die Funktion zum Indikator mfexpr* abgelegt. Weiterhin wird in kMaxima anstatt (func . rest) eine erweiterte Argumentliste verwendet, um die Syntax einer Spezialform besser wiederzugeben.

Quelltext:

(defmacro defmspec (func arg &body body)
  `(defun-prop (,func mspec) ,arg ,@body))

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

3.1.3 Das Makro defmvar

Globale Variable: *variable-initial-values*

Standardwert: #<HASH-TABLE :TEST EQL :COUNT 0>

Ist eine Hash-Tabelle mit allen Variablen und deren Anfangswerte, die mit dem Makro defmvar definiert sind. kMaxima nutzt die Einträge der Hash-Tabelle, wenn Optionsvariablen mit der Funktion $reset auf ihren Anfangswert zurückgesetzt werden.

Makro: defmvar var &rest val-and-doc

Das Makro definiert eine globale Variable var, deren Wert, wenn noch nicht vorhanden, in die Hash-Tabelle *variable-initial-values* eingetragen wird. Das Argument val-and-doc ist die Liste mit den weiteren Argumenten und enthält als erstes Element den Wert der Variablen sowie als zweites Element gegebenenfalls eine Zeichenkette für die Dokumentation. Jedes weitere Element der Liste wird ignoriert.

Mit der Nutzerfunktion $reset können Variablen, die mit defmvar definiert wurden, auf ihren Anfangswert zurückgesetzt werden.

Beispiel:

* (macroexpand '(defmvar x 100))
(PROGN
 (UNLESS (GETHASH 'X *VARIABLE-INITIAL-VALUES*)
   (SETF (GETHASH 'X *VARIABLE-INITIAL-VALUES*) 100))
 (DEFVAR X 100))
T
* (macroexpand '(defmvar y))
(PROGN
 (UNLESS (GETHASH 'Y *VARIABLE-INITIAL-VALUES*)
   (SETF (GETHASH 'Y *VARIABLE-INITIAL-VALUES*) NIL))
 (DEFVAR Y))
T

Quelltext:

(defmacro defmvar (var &rest val-and-doc)
  (cond ((> (length val-and-doc) 2)
         (setq val-and-doc (list (car val-and-doc) (second val-and-doc)))))
  `(progn
     (unless (gethash ',var *variable-initial-values*)
       (setf (gethash ',var *variable-initial-values*) ,(first val-and-doc)))
     (defvar ,var ,@val-and-doc)))

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

3.1.4 Das Makro errset

Globale Variable: *errset*

Standardwert: nil

Hat *errset* den Wert t, wird in einer mit dem Makro errset definierten Umgebung bei Auftreten eines Fehlers kMaxima durch Aufruf der Lisp-Funktion error abgebrochen.

Makro: errset &rest l

Mit dem Makro errset wird eine Umgebung definiert, die Fehler abfängt, wenn das Argument l ausgewertet wird. Hat die Variable *errset* den Wert nil, bricht die Ausführung des Programms bei einem Fehler nicht ab und der Rückgabewert ist nil. Kann das Argument erfolgreich ausgewertet werden, wird das Ergebnis als Element einer Liste zurückgegeben. Hat die Variable errset dagegen den Wert t, bricht die Ausführung von kMaxima mit dem Aufruf der Lisp-Funktion error ab.

Beispiele:

* (let ((errset nil)) (errset (/ 1 2)))
(1/2)
* (let ((errset nil)) (errset (/ 1 0)))
NIL
* (let ((errset t)) (errset (/ 1 0)))
; in: LAMBDA NIL
;     (/ 1 0)
; 
; caught STYLE-WARNING:
;   Lisp error during constant folding:
;   arithmetic error DIVISION-BY-ZERO signalled
;   Operation was SB-KERNEL::DIVISION, operands (1 0).
[...]

Quelltext:

(defmacro errset (&rest l)
  `(handler-case (list ,(car l))
     (error (e) (when errset (error e)))))

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

3.2 Allgemeine Hilfsfunktionen


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

3.2.1 Funktionen für die Eigenschaftsliste

Die Lisp-Eigenschaftsliste wird von kMaxima häufig genutzt, um Eigenschaften für Lisp-Symbole abzulegen. Diese Eigenschaften können Werte und Funktionen sein. Die Eigenschaftsliste erlaubt einen Programmierstil, der objektorientiert ist, ohne dass Mechanismen gebraucht werden, wie sie in anderen Programmiersprachen notwendig sind.

Um eine einheitliche Syntax zu ermöglichen, werden für das Setzen eines Wertes die Funktion putprop und das Makro defprop definiert. Im Unterschied zur Funktion putprop wertet das Makro defprop die Argumente nicht aus. Das erlaubt eine bequemere Schreibweise, da auf das Voranstellen des Quote-Operators ' verzichtet werden kann, wenn die Argumente Symbole sind. Mit der Funktion getprop kann eine Eigenschaft zu einem Symbol gelesen werden. Im Unterschied zur Lisp-Funktion get testet die Funktion getprop zunächst, ob das erste Argument ein Symbol ist. Ist dies nicht der Fall ist die Rückgabe nil.

Funktion: putprop sym val indic

Die Funktion putprop legt den Wert val zum Indikator indic auf der Eigenschaftsliste des Symbols sym ab. Die Funktion testet, ob das Argument sym ein Symbol ist. Ist sym kein Symbol, wird der Wert nil zurückgegeben.

Siehe auch die Funktionen defprop, getprop und getpropl.

Beispiele:

* (putprop 'sym 999 'val)
999
* (get 'sym 'val)
999
* (putprop 999 999 999)
NIL

Quelltext:

(defun putprop (sym val indic)
  (and (symbolp sym)
       (setf (get sym indic) val)))

Makro: defprop sym val indic

Das Makro defprop ruft die Funktion putprop auf, um den Wert val zum Indikator indic auf der Eigenschaftsliste des Symbols sym abzulegen. Im Unterschied zur Funktion putprop wertet das Makro defprop die Argumente nicht aus, so dass Symbole nicht quotiert werden müssen.

Siehe auch die Funktion getprop und getpropl.

Quelltext:

(defmacro defprop (sym val indic)
  `(putprop ',sym ',val ',indic))

Funktion: getprop sym indic

Die Funktion getprop holt den Wert zum Indikator indic von der Eigenschaftsliste des Symbols indic. Die Funktion testet zum Unterschied der Lisp-Funktion get, ob das Argument sym ein Symbol ist und gibt den Wert nil zurück, wenn dies nicht der Fall ist. Auch wird nil zurückgegeben, wenn kein Wert zum Indikator indic auf der Eigenschaftsliste abgelegt ist.

Quelltext:

* (putprop 'sym 999 'val)
999
* (getprop 'sym 'val)
999
* (getprop 999 'val)
NIL

Quelltext:

(defun getprop (sym indic)
  (and (symbolp sym)
       (get sym indic)))

Funktion: getpropl sym indicl

getpropl ist eine Verallgemeinerung der Funktion getprop, die eine Liste als zweites Argument erwartet und eine Liste zurückgibt, deren erstes Element der Indikator ist, zu dem der erste Eintrag auf der Eigenschaftsliste gefunden wurde. Die weiteren Elemente der Liste sind die folgenden Einträge der Eigenschaftsliste.

Beispiel:

* (defprop f 100 width)
100
* (defprop f round shape)
ROUND
* (symbol-plist 'f)
(SHAPE ROUND WIDTH 100)
* (getpropl 'f '(shape))
(SHAPE ROUND WIDTH 100)
* (getpropl 'f '(width))
(WIDTH 100)
* (getpropl 'f '(colour width))
(WIDTH 100)

Quelltext:

(defun getpropl (sym indicl)
  (cond ((symbolp sym)
         (setq sym (symbol-plist sym))
         (loop for tail on sym by #'cddr
               when (member (car tail) indicl :test #'eq)
               do (return tail)))
        (t (return-from getpropl nil))))

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

3.2.2 Informationslisten

Systemvariable: $props

Standardwert: []

Die Systemvariable $props ist eine Informationsliste für den Nutzer und enthält die Symbole, die vom Nutzer eine Eigenschaft erhalten haben.

$props hat die assign-Eigenschaft neverset. Der Systemvariablen kann daher vom Nutzer kein Wert zugewiesen werden.

Siehe zum Beispiel die Funktion op-setup, die Symbole in der Liste $props ablegt, die als Operator definiert werden.

Funktion: add2lnc item llist

Die Funktion add2lnc fügt der Liste llist das Element item hinzu. Üblicherweise ist ein item ein Symbol und llist eine der Informationslisten, die kMaxima zur Verfügung stellt. Die Informationslisten haben das interne Format ((mlist simp) $item1 $item2 ...). item kann auch eine Liste sein. Für Symbole oder Listen als Argument item verhält sich die Funktion etwas unterschiedlich.

Es wird zunächst geprüft, ob das Argument item bereits in der Liste enthalten ist. Der Test wird mit der Funktion memalike durchgeführt, die die Funktion alike1 nacheinander auf die Elemente der Liste anwendet. Ist item kein Element der Liste wird das Element am Ende der Liste hinzugefügt.

Für den Fall das das Argument item eine Liste ist, wird geprüft, ob das erste Element der Liste item bereits in der Liste enthalten ist. Ist dies der Fall, wird das vorhandene Element von der Liste gelöscht und das neue Element an das Ende der Liste angehängt.

Die Rückgabe ist die modifizierte Liste llist.

Seiteneffekte: Das Argument llist wird modifiziert und enthält nach dem Aufruf der Funktion eine aktualisierte Liste.

Beispiele: Die ersten Beispiele zeigen die übliche Verwendung der Funktion add2lnc. Symbole werden hier der Informationsliste $props hinzugefügt.

* $props
((MLIST SIMP))
* (add2lnc '$a $props)
((MLIST SIMP) $A)
* (add2lnc '$b $props)
((MLIST SIMP) $A $B)
* (add2lnc '$c $props)
((MLIST SIMP) $A $B $C)
* (add2lnc '$b $props)
((MLIST SIMP) $A $B $C)

Die Möglichkeit einer Liste als erstes Argument wird von Maxima genutzt, um die Abhängigkeit einer Funktion von Variablen in der Informationsliste $dependencies zu aktualisieren. Hier sind f(x,y) und g(x,y) zwei Funktionen, die von den Variablen x und y abhängen sollen. Im letzten Beispiel wird die Abhängigkeit von den Variablen a und b neu definiert. Der alte Eintrag ist entfernt.

* (defvar $dependencies '((mlist simp)))
$DEPENDENCIES
* (add2lnc '($f $x $y) $dependencies)
((MLIST SIMP) ($F $X $Y))
* (add2lnc '($g $x $y) $dependencies)
((MLIST SIMP) ($F $X $Y) ($G $X $Y))
* (add2lnc '($f $a $b) $dependencies)
((MLIST SIMP) ($G $X $Y) ($F $A $B))

Quelltext:

(defun add2lnc (item llist)
  (unless (memalike item (if (mlistp llist) (cdr llist) llist))
    (unless (atom item)
      (setf llist
            (delete (assoc (car item) llist :test #'equal)
                    llist :count 1 :test #'equal)))
    (nconc llist (list item))))

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

3.3 Testfunktionen


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

3.3.1 Allgemeine Testfunktionen

Funktion: fixnump x

Ist das Argument x eine ganze Zahl vom Typ fixnum, ist das Ergebnis true und ansonsten false.

Der Bereich der ganzen Zahlen vom Typ fixnum ist abhängig von der Lisp-Implementation. Der größte Wert ist most-positive-fixnum und der kleinste ist most-negative-fixnum.

Siehe auch die Funktion bignump.

Quelltext:

(defun fixnump (x)
  (typep n 'fixnum))

Funktion: bignump x

Ist das Argument x eine ganze Zahl vom Typ bignum, ist das Ergebnis true und ansonsten false.

Siehe auch die Funktion fixnump.

Quelltext:

(defun  bignump (x)
  (typep x 'bignum))

Funktion: mfunctionp x

Ist das Argument x eine Funktion oder ein Symbol, das eine Funktion bezeichnet, dann ist die Rückgabe t und ansonsten nil. Die Funktion mfunctionp ist eine Erweiterung der Lisp-Funktion functionp, die auch Symbole berücksichtigt, die eine Funktion als Wert haben.

Beispiele:

* (functionp #'meval)
T
* (functionp 'meval)
NIL
* (mfunctionp 'meval)
T

Quelltext:

(defun mfunctionp (x)
  (cond ((symbolp x)
         (and (not (macro-function x))
              (fboundp x) t))
        ((functionp x))))

Globale Variable: *alphabet*

Standardwert: (#\_ #\%)

Die globale Liste *alphabet* enthält die Zeichen, die in kMaxima zusätzlich zu den Zeichen A ... Z und a ... z alphabetische Zeichen sind. Die Funktion alphabetp berücksichtigt bei einem Test die in *alphabet* enthaltenen Zeichen.

kMaxima-Bezeichner können alle Zeichen enthalten, die alphabetisch sind. Sonderzeichen, die der globalen Variablen *alphabet* hinzugefügt werden, können zusätzlich in Bezeichnern verwendet werden.

Funktion: alphabetp ch

Hat das Ergebnis true, wenn das Argument ch ein alphabetisches Zeichen ist. Alphabetisch sind die Zeichen A ... Z und a ... z sowie die Zeichen, die in der globalen Variablen *alphabet* enthalten sind.

Alphabetische Zeichen können in einem kMaxima-Bezeichner verwendet werden. Wenn ein Token mit der Funktion scan-token vom Parser eingelesen wird, dann endet das Einlesen des Tokens mit dem ersten Zeichen, das kein alphabetisches Zeichen ist.

Beispiele:

* (alphabetp #\A)
T
* (alphabetp #\+)
NIL

Quelltext:

(defun alphabetp (ch)
  (and (characterp ch)
       (or (alpha-char-p ch)
           (member ch *alphabet*))))

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

3.3.2 Teste kMaxima-Ausdrücke

kMaxima-Ausdrücke haben immer die Form ((op) arg_1 arg_2 ...). Das erste Element der Liste ist eine Liste mit dem Hauptoperator des Ausdrucks als erstes Element. Dann folgen die Argumente des Operators. Sehr häufig muss getestet werden, ob ein bestimmter Operator vorliegt. Hierfür werden in diesem Kapitel Testfunktionen bereit gestellt.

Funktion: moperatorp x op

Die Rückgabe ist t, wenn der Operator op der Hauptoperator des Ausdrucks x ist. Die Funktion testet, ob ein gültiger kMaxima-Ausdruck vorliegt. Ist dies nicht der Fall, ist die Rückgabe nil.

Beispiele:

* (moperatorp '((mplus) $a $b) 'mplus)
T
* (moperatorp '((mplus) $a $b) 'mtimes)
NIL
* (moperatorp '((mplus) ((mtimes) 2 $a) $b) 'mtimes)
NIL
* (moperatorp 100 'mplus)
NIL
* (moperatorp '(a b c) 'mplus)
NIL

Bemerkung:

Im Original Maxima gibt es eine Funktion op-equalp, die eine beliebige Anzahl an Operatoren als Argument akzeptiert und mit der Lisp-Funktion equal testet. Die hier definierte Funktion kopiert die Syntax anderer Testfunktionen wie mplusp oder mexptp.

Quelltext:

(defun moperatorp (x op)
  (and (consp x)
       (consp (car x))
       (eq (caar x) op)))

Funktion: mminusp x

Testet, ob das Argument x ein mminus-Ausdruck ist, also den Operator mminus für die Negation als Hauptoperator hat. Siehe auch die Funktion moperatorp, die allgemeiner definiert ist und einen Operator als weiteres Argument akzeptiert.

Quelltext:

(defun mminusp (x)
  (and (consp x)
       (consp (car x))
       (eq (caar x) 'mminus)))

Funktion: mplusp x

Testet, ob das Argument x ein mplusp-Ausdruck ist, also den Operator mplus für eine Summe als Hauptoperator hat. Siehe auch die Funktion moperatorp, die allgemeiner definiert ist und einen Operator als weiteres Argument akzeptiert.

Quelltext:

(defun mplusp (x)
  (and (consp x)
       (consp (car x))
       (eq (caar x) 'mplus)))

Funktion: mtimesp x

Testet, ob das Argument x ein mtimesp-Ausdruck ist, also den Operator mtimes für ein Produkt als Hauptoperator hat. Siehe auch die Funktion moperatorp, die allgemeiner definiert ist und einen Operator als weiteres Argument akzeptiert.

Quelltext:

(defun mtimesp (x)
  (and (consp x)
       (consp (car x))
       (eq (caar x) 'mtimes)))

Funktion: mexptp x

Testet, ob das Argument x ein mexptp-Ausdruck ist, also den Operator mexpt für die Exponentiation als Hauptoperator hat. Siehe auch die Funktion moperatorp, die allgemeiner definiert ist und einen Operator als weiteres Argument akzeptiert.

Quelltext:

(defun mexptp (x)
  (and (consp x)
       (consp (car x))
       (eq (caar x) 'mexpt)))

Funktion: mlistp x

Testet, ob das Argument x ein mlistp-Ausdruck ist, also den Operator mlist für eine Liste als Hauptoperator hat. Siehe auch die Funktion moperatorp, die allgemeiner definiert ist und einen Operator als weiteres Argument akzeptiert.

Quelltext:

(defun mlistp (x)
  (and (consp x)
       (consp (car x))
       (eq (caar x) 'mlist)))

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

3.3.3 Teste kMaxima-Zahlen

Funktion: mnumberp x

Testet, ob das Argument x eine kMaxima-Zahl ist. kMaxima-Zahlen sind ganze Zahlen, Gleitkommazahlen sowie rationale Zahlen und große Gleitkommazahlen.

Quelltext:

(defun mnumberp (x)
  (or (numberp x)
      (and (consp x)
           (consp (car x))
           (member (caar x) '(rat bigfloat))
           t)))

Funktion: ratnump x

Testet, ob das Argument x eine rationale Zahl ist. Rationale Zahlen werden nicht als eine Lisp-Zahl, sondern als ein Ausdruck mit dem Operator rat dargestellt.

Quelltext:

(defun ratnump (x)
  (and (consp x)
       (consp (car x))
       (eq (caar x) 'rat)))

Funktion: bigfloatp x

Testet, ob das Argument x eine große Gleitkommazahl ist.

Quelltext:

(defun bigfloatp (x)
  (and (consp x)
       (consp (car x))
       (eq (caar x) 'bigfloat)))

Funktion: zerop1 x

Testet, ob das Argument x die Zahl Null ist. Im Unterschied zur Lisp-Funktion zerop, werden auch große Gleitkommazahlen auf den Wert Null getestet. Siehe auch die Funktionen onep und onep1.

Beispiele:

* (zerop1 0)
T
* (zerop1 0.0)
T
* (zerop1 ($bfloat 0))
T

Quelltext:

(defun zerop1 (x)
  (or (and (numberp x)
           (zerop x))
      (and (bigfloatp x)
           (zerop (second x)))))

Funktion: onep x

Testet, ob das Argument x eine Lisp-Zahl mit dem Wert Eins ist. onep ist vergleichbar mit der Lisp-Funktion zerop.

Siehe auch die Funktionen onep1 und zerop1.

Beispiele:

* (onep 1)
T
* (onep 1.0)
T

Bemerkung:

Das Original Maxima hat auch die Funktion onep. Diese testet jedoch nur, ob das Argument die ganze Zahl 1 ist. Die hier definierte Funktion hat dagegen auch für eine Gleitkommazahl mit dem Wert 1.0 das Ergebnis t. Das entspricht der Funktionalität der entsprechenden Lisp-Funktion zerop.

Quelltext:

(defun onep (x)
  (zerop (- x 1)))

Funktion: onep1 x

Testet, ob das Argument x eine Zahl mit dem Wert Eins ist. Im Unterschied zur Funktion onep werden auch große Gleitkommazahlen auf den Wert Eins getestet.

Beispiel:

* (onep1 ($bfloat 1))
T

Quelltext:

(defun onep1 (x)
  (or (and (numberp x)
           (zerop (- x 1)))
      (and (bigfloatp x)
           (zerop (second (sub x 1))))))

Funktion: minusp1 x

Testet, ob das Argument x eine negative Zahl ist. Das Argument kann eine Lisp-Zahl sowie eine rationale Zahl oder große Gleitkommazahl sein.

Beispiele:

* (minusp1 -1)
T
* (minusp1 -1.0)
T
* (minusp1 ($bfloat -1))
T
* (minusp1 ($bfloat 2))
NIL

Quelltext:

(defun minusp1 (x)
  (cond ((realp x) (minusp x))
        ((ratnump x) (minusp (rat-num x)))
        ((bigfloatp x) (minusp (cadr x)))))

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

3.3.4 Teste Symbole mit Eigenschaften

Funktion: decl-constant x

Testet, ob das Argument x ein Symbol ist, das als konstant deklariert ist. Siehe auch die Funktion mconstantp.

Bemerkung:

Eigenschaften wie die, das ein Symbol eine Konstante repräsentiert, werden im Original Maxima in eine Datenbank abgelegt. Diese ist hier noch nicht implementiert. Um die zugehörige Funktionalität vorab implementieren zu können, erwartet die Funktion decl-constant die entsprechende Eigenschaft auf der Eigenschaftsliste des Symbols. Später kann die Funktion decl-constant leicht umformuliert werden, ohne das der bereits vorhandene Code geändert werden muss.

Quelltext:

(defun decl-constant (x)
  (getprop x '$constant))

Funktion: mconstantp x

Testet, ob das Argument x eine Lisp-Zahl oder ein Symbol ist, das als konstant deklariert ist. So sind zum Beispiele die Symbole %e, %pi, %gamma, %phi oder %i als konstant deklariert.

Siehe auch die Funktion decl-constant.

Bemerkung:

Das Original Maxima hat die Funktion maxima-constantp, die mit dieser Funktion vergleichbar ist. Rationale Zahlen und große Gleitkommazahlen geben nicht das Ergebnis t für eine Konstante zurück. Dies erscheint nicht konsistent. Ein Grund für diese Inkonsistenz ist noch nicht gefunden.

Quelltext:

(defun mconstantp (x)
  (or (numberp x)
      (decl-constant x)))

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

3.4 Syntax der Bezeichner


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

3.4.1 Konvertierung zwischen Groß- und Kleinschreibung

Im Gegensatz zu Lisp unterscheidet kMaxima Groß- und Kleinschreibung. Dabei besteht die Konvention, dass einem kMaxima-Bezeichner der klein geschrieben ist, ein groß geschriebener Lisp-Bezeichner entspricht. Umgekehrt entspricht einem groß geschriebenen kMaxima-Bezeichner ein klein geschriebener Lisp-Bezeichner. Bezeichner in gemischter Groß- und Kleinschreibung werden nicht konvertiert. Diese Konventionen werden von den Funktionen print-invert-case, maybe-invert-string und intern-invert-case implementiert.

Funktion: print-invert-case sym

Die folgende Implementierung der Funktion print-invert-case hängt vom verwendeten Lisp ab. Hier wird die Implementierung für SBCL gezeigt. Das Argument sym muss ein Symbol sein. Die Rückgabe der Funktion ist eine Zeichenkette.

Beispiele:

Die Beispiele zeigen die Konvertierung für klein- und großgeschriebene Symbole sowie Symbole in gemischter Schreibweise.

* (print-invert-case '|abc|)
"ABC"
* (print-invert-case '|ABC|)
"abc"
* (print-invert-case '|aBc|)
"aBc"

Quelltext:

(let ((local-table (copy-readtable nil)))
  (setf (readtable-case local-table) :invert)
  (defun print-invert-case (sym)
    (let ((*readtable* local-table)
          (*print-case* :upcase))
      (princ-to-string sym))))

Funktion: maybe-invert-string str

Die Funktion maybe-invert-string hat dieselbe Aufgabe wie die Funktion print-invert-case. Die Funktion maybe-invert-string erwartet jedoch eine Zeichenkette str als Argument. Die Rückgabe ist wieder eine Zeichenkette.

Beispiele:

Dieselben Beispiele wie oben. Das Argument muss eine Zeichenkette sein. Die Rückgabe ist eine Zeichenkette.

* (maybe-invert-string "abc")
"ABC"
* (maybe-invert-string "ABC")
"abc"
* (maybe-invert-string "aBc")
"aBc"

Quelltext:

(defun maybe-invert-string (str)
  (let ((all-upper t)
        (all-lower t))
    (dotimes (i (length str))
      (let ((ch (char str i)))
        (when (both-case-p ch)
          (if (upper-case-p ch)
              (setq all-lower nil)
              (setq all-upper nil)))))
    (cond (all-upper (string-downcase str))
          (all-lower (string-upcase str))
          (t str))))

Funktion: intern-invert-case str

Die Funktion intern-invert-case erwartet eine Zeichenkette str als Argument. Die Funktion ruft die Funktion maybe-invert-string auf. Im Unterschied zur Funktion maybe-invert-string ist die Rückgabe ein Symbol, das in das Package :kmaxima geschrieben wird.

Beispiele:

Zeichenketten werden in ein Symbol umgewandelt und in das Package :kmaxima geschrieben.

* (intern-invert-case "abc")
ABC
:INTERNAL
* (intern-invert-case "aBc")
|aBc|
:INTERNAL

Quelltext:

(defun intern-invert-case (str)
  (intern (maybe-invert-string str) :kmaxima))

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

3.4.2 Zerlegen von Symbolen und Zeichenketten

Häufig werden Zahlen, Symbole oder Zeichenketten als eine Liste ihrer Zeichen benötigt. Dies wird von der Funktion exploden geleistet. Die Funktion enthält Algorithmen für die Zerlegung von Symbolen, Gleitkommazahlen und ganzen Zahlen. Alle anderen Argumente der Funktion exploden werden mit der Funktion format in eine Zeichenkette umgewandelt und dann in eine Liste zerlegt.

Die Umwandlung von Gleitkommazahlen in die Liste der Zeichen wird von den Variablen $fpprintprec und $maxfpprintprec kontrolliert. Der Nutzer legt mit der Optionsvariablen $fpprintprec die Anzahl der Stellen einer Gleitkommazahl fest. Die globale Variable *maxfpprintprec* enthält die maximale Anzahl der Stellen einer Gleitkommazahl. Hat die Optionsvariable $fpprintprec den Wert 0 oder ist der Wert größer als die maximal Anzahl an Stellen, wird für die Umwandlung in eine Zeichenkette die Anzahl der Stellen in *maxfpprintprec* verwendet.

Im Unterschied zum Original Maxima ist die Umwandlung von großen Gleitkommazahlen noch nicht implementiert.

Funktion: exploden sym

Umwandlung von ganzen Zahlen, Gleitkommazahlen, Symbolen und Zeichenketten in eine Liste von Zeichen. exploden ruft für die Umwandlung von Symbolen die Funktion print-invert-case , die die Konventionen der Klein- und Großschreibung von Symbolen implementiert.

Beispiele:

* (exploden 123)
(#\1 #\2 #\3)
* (exploden 123.45)
(#\1 #\2 #\3 #\. #\4 #\5)
* (exploden 'symbol)
(#\s #\y #\m #\b #\o #\l)
* (exploden "String")
(#\S #\t #\r #\i #\n #\g)

Quelltext:

(defun exploden (sym)
  (declare (special *maxfpprintprec* $fpprintprec))
  (let (str)
    (cond ((symbolp sym)
           (setq str (print-invert-case sym)))
          ((floatp sym)
           (let ((a (abs sym))
                 (printprec (if (or (= $fpprintprec 0)
                                    (> $fpprintprec *maxfpprintprec*))
                                *maxfpprintprec*
                                $fpprintprec)))
             (multiple-value-bind (form width)
               (cond ((or (zerop a) (<= 1 a 1e7))
                      (values "~vf" (+ 1 printprec)))
                     ((<= 0.001 a 1)
                      (values "~vf" (+ printprec
                                       (cond ((< a 0.01) 3)
                                             ((< a 0.1) 2)
                                             (t 1)))))
                     (t
                      (values "~ve" (+ 5 printprec))))
               (setq str (format nil form width sym)))
             (setq str (string-trim " " str))))
          ((integerp sym)
           (let ((leading-digit (if (> *print-base* 10) #\0 )))
             (setq str (format nil "~A" sym))
             (setq str (coerce str 'list))
             (if (and leading-digit
                      (not (digit-char-p (car str) 10)))
                 (setq str (cons leading-digit str)))
             (return-from exploden str)))
          (t (setq str (format nil "~A" sym))))
    (coerce str 'list)))

Funktion: implode lis

Die Funktion implode leistet die zu der Funktion exploden umgekehrte Aufgabe. Eine Liste mit Zeichen wird zu einem Symbol zusammengesetzt, das mit der Funktion intern-invert-case in das Package :kmaxima geschrieben wird. Gegenüber der Originalfunktion in Maxima ist diese Implementation erheblich vereinfacht und akzeptiert nur Listen aus Zeichen.

Beispiele:

Listen aus Zeichen werden in ein Symbol umgewandelt und in das Package :kmaxima geschrieben.

* (implode '(#\1 #\2 #\3))
|123|
NIL
* (implode '(#\1 #\2 #\3 #\. #\4 #\5))
|123.45|
NIL
* (implode '(#\s #\y #\m #\b #\o #\l))
SYMBOL
:INHERITED
* (implode '(#\S #\t #\r #\i #\n #\g))
|String|
NIL

Quelltext:

(defun implode (lis)
  (intern-invert-case (coerce lis 'string)))

Funktion: symbolconc &rest syms

Ist eine Funktion, die Zahlen, Symbole, Zeichenketten und sonstige Argumente zu einem Symbol zusammensetzt. Die Funktion akzeptiert eine beliebige Anzahl an Argumenten. Das Symbol wird dem aktuellen Package hinzugefügt.

Beispiel:

Zahlen, Symbole und Zeichenketten werden zu einem Symbol zusammengesetzt.

* (symbolconc 1 'a "string" '+ 10.0)
|1Astring+10.0|
NIL

Quelltext:

(defun symbolconc (&rest syms)
  (intern (apply #'concatenate 'string
                 (mapcar #'(lambda (sym)
                             (cond ((floatp sym)
                                    (format nil "~S" sym))
                                   ((integerp sym)
                                    (format nil "~D" sym))
                                   ((symbolp sym)
                                    (symbol-name sym))
                                   (t sym)))
                         syms))))

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

3.4.3 Alias und Reversealias

Globale Variable: $aliases

Standardwert: ((mlist simp))

Liste der Symbole, die mit der Funktion $alias einen Alias-Namen erhalten haben.

Funktion: getalias

Der Parser liest Symbole von der Eingabe. Einem Symbole kann ein Alias-Name zugeordnet werden. Der Alias-Name wird zum Indikator alias auf der Eigenschaftsliste zum Symbol abgelegt. Die Funktion getalias prüft, ob ein Alias-Name vorliegt und gibt diesen gegebenenfalls zurück. Ansonsten wird das Argument der Funktion zurückgegeben. Der Fall des Symbols $false muss separat geprüft werden. Es ist nicht möglich den Alias nil für das Symbol $false zu nutzen, da die Funkion getprop in diesem Fall den Rückgabewert nil hat, was ein signalisieren würde, dass kein Alias gefunden wurde.

Beispiele:

Wenn kMaxima die Zeichenfolge sin von der Eingabe liest, wird diese zunächst als ein Maxima-Token interpretiert und in die interne Darstellung $sin umgewandelt. $sin steht nun für die Sinusfunktion, die nicht als Verbfunktion sondern als Substantivfunktion implementiert ist. Zum Symbol $sin ist daher die Substantivform %sin als Alias abgelegt. Die Funktion getalias gibt diese Substantivform zurück.

* (defprop $sin %sin alias)
%SIN
* (getalias '$sin)
%SIN

Die Aliase der Symbole $true und $false sind T und NIL.

* (getalias '$true)
T
* (getalias '$false)
NIL

Quelltext:

(defun getalias (x)
  (cond ((getprop x 'alias))
        ((eq x '$false) nil)
        (t x)))

Funktion: amperchk name

Die Funktion amperchk akzeptiert Symbole und Zeichenketten als Argument. Ein Symbol wird sofort zurückgegeben. Ist das Argument eine Zeichenkette wird mit der Funktion getopr geprüft, ob zu dieser Zeichenkette ein Symbol vorhanden ist, dass einen Operator bezeichnet. Ist dies nicht der Fall, wird die Zeichenkette zu einem Maxima-Symbol umgewandelt. Das ist ein Lisp-Symbol dem ein Dollarzeichen vorangestellt wird.

Beispiel:

Die Zeichenkette "+" ist der Name des Operators für die Addition. Das Symbol das die Addition bezeichnet ist mplus. Die Zeichenkette "f" wird in ein Maxima-Symbol $f umgewandelt.

* (amperchk "+")
MPLUS
* (amperchk "f")
$F

Quelltext:

(defun amperchk (name)
  (cond ((symbolp name) name)
        ((stringp name)
         (getalias (or (getopr0 name)
                       (implode (cons #\$ (coerce name 'list))))))))

Funktion: $alias form

Die Nutzerfunktion $alias definiert einen Alias-Namen für ein Symbol. Der Alias-Name ist wieder ein Symbol. Hat ein Symbol einen Alias-Namen wird das Symbol beim Einlesen vom Parser durch den Alias-Namen ersetzt. Dazu wird zu dem Symbol zum Indikator 'alias der Alias-Name auf die Eigenschaftsliste abgelegt. Umgekehrt erhält das Symbol das den Alias-Namen repräsentiert einen Eintrag zum Indikator 'reversealias auf der Eigenschaftsliste. Wird ein Ausdruck auf der Anzeige ausgegeben, dann werden Symbole, die einen Eintrag 'reversealias haben, durch diesen ersetzt. Symbole, die einen Alias-Namen erhalten, werden in die Informationsliste $aliases eingetragen.

Beispiel:

Die imaginäre Einheit wird von kMaxima als %i dargestellt. Bevorzugt der Nutzer die Darstellung I, kann er I als den Alias-Namen für %i definieren. Liest der Parser einen Ausdruck wie 2*I, dann wird das Symbol |$I| durch das Symbol $%I ersetzt, das intern die imaginäre Einheit repräsentiert. Das Symbol $%I hat den Eintrag 'reversealias auf der Eigenschaftsliste. Wird der Ausdruck '((mtimes) 2 $%i) ausgegeben, dann wird das Symbol $%i für die Anzeige durch das vom Nutzer definierte Symbol |$I| ersetzt.

(%i1) alias(I, %i);
(%o1) [I]
(%i2) expr : 2*I;
(%o2) 2*I
(%i3) quit();
0
* $expr;
((MTIMES) 2 $%I)
* (symbol-plist '|$I|)
(ALIAS $%I)
* (symbol-plist '$%i)
(REVERSEALIAS |$i| ASSIGN NEVERSET)

Quelltext:

(defmspec $alias (form)
  (if (oddp (length (setq form (cdr form))))
      (merror "alias: takes an even number of arguments."))
  (do ((l nil (cons (alias (pop form) (pop form)) l)))
      ((null form)
       `((mlist simp),@(nreverse l)))))

Funktion: alias x y

Quelltext:

(defun alias (x y)
  (unless (and (symbolp x) (symbolp y))
    (merror "alias: the arguments must be symbolic names: found ~M and ~M"
            x y))
  (cond ((eq x y) y)
        ((get x 'reversealias)
         (if (not (eq x y))
             (merror "alias: ~M already is aliased." x)))
        (t
         (putprop x y 'alias)
         (putprop y x 'reversealias)
         (add2lnc y $aliases)
         y)))

Funktion: remalias x &optional remp

Quelltext:

(defun remalias (x &optional remp)
  (let ((y (and (or remp
                    (member x (cdr $aliases) :test #'equal))
                (getprop x 'reversealias))))
    (cond ((and y (eq x '%derivative))
           (remprop x 'reversealias)
           (setf $aliases (delete x $aliases :count 1 :test #'eq))
           (remprop '$diff 'alias) '$diff)
          (y
           (remprop x 'reversealias)
           (remprop x 'noun)
           (setf $aliases (delete x $aliases :count 1 :test #'eq))
           (remprop (setq x y) 'alias) (remprop x 'verb) x))))

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

3.4.4 Verb- und Substantivform

Die Funktionen $nounify und $verbify implementieren den Mechanismus der Verb- und Substantivformen von Symbolen. Die Verbform eines Symbols ist ein Symbol dem ein Dollarzeichen vorangestellt ist. Die Substantivform ist ein Symbol dem ein Prozentzeichen vorangestellt ist. Zum Beispiel hat die Sinusfunktion die Verbform $sin und die Substantivform %sin.

Funktion: $nounify x

Die Funktion $nounify ist als eine Maxima-Nutzerfunktion implementiert, die als Argument x ein Symbol oder eine Zeichenkette akzeptiert. Die Rückgabe ist das Symbol in der Substantivform. Zunächst wird mit der Funktion amperchk ein String in ein Maxima-Symbol umgewandelt. Das ist ein Symbol mit einem vorangestelltem Dollarzeichen. Ausnahme sind Zeichenketten, die der Name eines Operators sind. Zum Beispiel ist die Zeichenkette "+" der Name des Additionsoperators +. In diesem Fall wird die Zeichenkette durch das Symbol für den Operator ersetzt, was für die Addition das Symbol mplus ist.

Nun prüft die Routine mit getprop x 'verb, ob das Symbol bereits eine Substantivform hat, die auf der Eigenschaftsliste der Verbform des Symbols abgelegt ist. Als nächstes wird mit getprop 'x 'noun geprüft, ob das Symbol als eine Substantivform deklariert ist. Treffen die beiden vorhergehenden Tests nicht zu, wird das zur Verbform gehörende Symbol in der Substantivform erzeugt und die Verb- und Substantivformen werden auf der Eigenschaftsliste abgelegt. Ist das Argument bereits ein Symbol in der Substantivform, wird dieses zurückgegeben.

Beispiele:

$nounify wird mit der Zeichenkette "sin" aufgerufen. Die Rückgabe ist das Symbol %sin, das die Substantivform bezeichnet. Auf der Eigenschaftsliste wird zum Symbol $sin in der Verbform zum Indikator verb das Symbol in der Substantivform %sin abgelegt. Umgekehrt wird zum Symbol %sin die Verbform $sin zum Indikator noun auf der Eigenschaftsliste eingetragen.

* ($nounify "sin")
%SIN
* (symbol-plist '$sin)
(VERB %SIN)
* (symbol-plist '%sin)
(NOUN $SIN)

In diesem Beispiel wird $nounify mit dem Symbol $cos als Argument aufgerufen. Wie im obigen Beispiel wird die Substantivform zurückgegeben

* ($nounify '$cos)
%COS
* (symbol-plist '$cos)
(VERB %COS)
* (symbol-plist '%cos)
(NOUN $COS)

Quelltext:

(defun $nounify (x)
  (if (not (or (symbolp x) (stringp x)))
      (merror "nounify: argument must be a symbol or a string."))
  (setq x (amperchk x))
  (cond ((getprop x 'verb))
        ((getprop x 'noun) x)
        (t
         (let* ((y (exploden x))
                (u (eql (car y) #\$)))
           (cond ((or u (not (eql (car y) #\%)))
                  (setq y (implode (cons #\% (if u (cdr y) y))))
                  (putprop y x 'noun)
                  (putprop x y 'verb))
                 (t x))))))

Funktion: $verbify x

Die Funktion $verbify gibt das zu einem Symbol oder einer Zeichenkette gehörende Symbol x in der Verbform zurück. Für den Fall, dass das Argument ein Symbol in der Substantivform ist, wird die Funktion $nounify

mit der Verbform des Argumentes aufgerufen, um die Verb- und Substantivformen in die Eigenschaftsliste einzutragen.

Beispiele:

Wird die Funktion $verbify mit einer Zeichenkette aufgerufen, wird das entsprechende Maxima-Symbol mit einem vorangestelltem Dollarzeichen zurückgegeben. Es werden keine Eintragungen in die Eigenschaftsliste der Symbole vorgenommen. Im zweiten Beispiel wird $verbify mit dem Symbol %tan aufgerufen. Jetzt werden die Verb- und Substantivformen in die Eigenschaftsliste eingetragen.

* ($verbify "tan")
$TAN
* (symbol-plist '$tan)
NIL
* (symbol-plist '%tan)
NIL
* ($verbify '%tan)
$TAN
* (symbol-plist '%tan)
(NOUN $TAN)
* (symbol-plist '$tan)
(VERB %TAN)

Quelltext:

(defun $verbify (x)
  (if (not (or (symbolp x) (stringp x)))
      (merror "verbify: argument must be a symbol or a string."))
  (setq x (amperchk x))
  (cond ((getprop x 'noun))
        ((eq x '||) x)
        ((and (char= (char (symbol-name x) 0) #\%)
              (prog2
                ($nounify (implode (cons #\$ (cdr (exploden x)))))
                (getprop x 'noun))))
        (t x)))

Funktion: maxima-symbol-p sym

Die Funktion maxima-symbol-p testet, ob ein Symbol oder eine Zeichenkette einen kMaxima-Bezeichner repräsentiert, also ob das Symbol oder die Zeichenkette als erstes Zeichen % oder $ hat.

Beispiele:

* (maxima-symbol-p 100)
NIL
* (maxima-symbol-p '$float)
#\$

Quelltext:

(defun maxima-symbol-p (sym)
  (if (or (symbolp sym)
          (stringp sym))
      (car (member (char (string sym) 0) '(#\$ #\%)))))

Funktion: stripdollar x

Die Funktion stripdollar entfernt das Zeichen % oder $ von einem kMaxima-Bezeichner.

Beispiele:

* (stripdollar '$float)
FLOAT
:INHERITED
* (stripdollar '%sin)
SIN
:INHERITED
* (stripdollar "$sin")
|sin|
NIL

Quelltext:

(defun stripdollar (x)
  (cond ((numberp x) x)
        ((null x) 'false)
        ((eq x t) 'true) 
        ((maxima-symbol-p x)
         (intern (subseq (string x) 1)))
        (t x)))

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

3.5 Funktionen für Ausdrücke


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

3.5.1 Operatoren und Argumente holen

Funktion: mop form

Gibt den Hauptoperator des Ausdrucks form zurück, der ein gültiger kMaxima-Ausdruck sein muss. Die Funktion mop prüft dabei, ob ein mqapply-Ausdruck vorliegt. Es ist ein Fehler keinen gültigen kMaxima-Ausdruck als Argument an die Funktion zu übergeben. In diesem Fall bricht die Ausführung mit einem Lisp-Fehler ab.

Siehe auch die Funktion margs.

Beispiel:

* (mop '((mplus) a b))
MPLUS
* (mop '((mqapply) ((f array) x) a b))
((F ARRAY) X)

Quelltext:

(defun mop (form)
  (if (eq (caar form) 'mqapply)
      (cadr form)
      (caar form)))

Funktion: margs form

Gibt die Argumente des Hauptoperators des Ausdrucks form zurück. Das Argument form muss ein gültiger kMaxima-Ausdruck sein, ansonsten wird ein Lisp-Fehler signalisiert. Die Funktion margs prüft dabei, ob ein mqapply-Ausdruck vorliegt.

Siehe auch die Funktion mop.

Beispiele:

* (margs '((mplus) a b))
(A B)
* (margs '((mqapply) ((f array) x) a b))
(A B)

Quelltext:

(defun margs (form)
  (if (eq (caar form) 'mqapply)
      (cddr form)
      (cdr form)))

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

3.5.2 Vergleiche Ausdrücke

kMaxima-Ausdrücke werden als Lisp-Listen der Form ((op) arg1 arg2 ...) dargestellt. Äquivalente Ausdrücke können eine verschiedene interne Darstellung haben, wenn die Operatoren op Attribute haben. Zum Beispiel sind die beiden kMaxima-Ausdrücke ((mplus) $A $B) und ((mplus simp) $A $B) äquivalent und stellen die Addition a+b dar. Daher können zwei Ausdrücke nicht mit der Lisp-Funktion equalp auf äquivalenz getestet werden.

Die folgenden Funktionen testen, ob zwei kMaxima-Ausdrücke äquivalent sind. Die Attribute der Operatoren werden ignoriert. Die Funktion alike1 wird aufgerufen, um zwei kMaxima-Ausdrücke auf Äquivalenz zu testen. Die Funktion alike vergleicht die Listen mit den Argumenten der Ausdrücke.

Funktion: alike1 x y

Die Funktion alike1 testet, ob die beiden Argumente x und y äquivalente Ausdrücke sind. Die Argumente sind beliebige kMaxima-Ausdrücke. Sind die Argumente äquivalent ist die Rückgabe t und ansonsten nil. Die Argumente werden auf syntaktische Äquivalenz geprüft. Daher können mathematisch äquivalente Ausdrücke gegenüber einem Test mit der Funktion alike1 voneinander verschieden sein. Nicht berücksichtigt werden beim Vergleich auf Äquivalenz die Attribute der Operatoren. Daher sind zum Beispiel ((mplus simp) $a $b) und ((mplus) $a $b) äquivalent.

Siehe auch die Funktion alike, um Listen miteinander zu vergleichen und memalike, um zu prüfen, ob ein Element in einer Liste enthalten ist.

Beispiel:

Das Beispiel zeigt den Vergleich von zwei Ausdrücken, die beide die Addition a+b repräsentieren.

* (alike1 '((mplus) $a $b) '((mplus simp) $a $b))
T

Quelltext:

(defun alike1 (x y)
  (labels ((memqarr (ll)
             (if (member 'array ll :test #'eq) t)))
    (cond ((eq x y))
          ((atom x) (equal x y))
          ((atom y) nil)
          (t
           (and (not (atom (car x)))
                (not (atom (car y)))
                (eq (caar x) (caar y))
                (eq (memqarr (cdar x)) (memqarr (cdar y)))
                (alike (cdr x) (cdr y)))))))

Funktion: alike x y

Die Argumente x und y sind Listen, deren Elemente nacheinander mit der Funktion alike1 auf Äquivalenz getestet werden. Üblicherweise sind handelt es sich dabei um die Listen mit den Argumenten eines kMaxima-Ausdrucks.

Quelltext:

(defun alike (x y)
  (do ((x x (cdr x))
       (y y (cdr y)))
      ((atom x) (equal x y))
    (if (or (atom y)
            (not (alike1 (car x) (car y))))
        (return nil))))

Funktion: memalike x l

Die Funktion memalike sucht das Argument x in der Liste l. Die Äquivalenz wird mit der Funktion alike1 getestet.

Beispiele: Der Ausdruck 2*a+b enthält die Argument 2*a und $b. $a ist kein Argument des Ausdrucks.

* (memalike '((mtimes) 2 $A) '((mplus) ((mtimes) 2 $a) $b))
(((MTIMES) 2 $A) $B)
* (memalike '$b '((mplus) ((mtimes) 2 $a) $b))
($B)
* (memalike '$a '((mplus) ((mtimes) 2 $a) $b))
NIL

Quelltext:

(defun memalike (x l)
  (do ((l l (cdr l)))
      ((null l))
    (when (alike1 x (car l)) (return l))))

Funktion: free expr var

Testet, ob der Ausdruck expr frei von dem Argument var ist. Das Argument var kann ein Symbol oder ein beliebiger kMaxima-Ausdruck sein.

Siehe auch die Funktion freel.

Beispiele:

* (free '((mplus) $a ((mtimes) 2 $b)) 'mplus)
NIL
* (free '((mplus) $a ((mtimes) 2 $b)) '((mtimes) 2 $b))
NIL
* (free '((mplus) $a ((mtimes) 2 $b)) '((mexpt) 2 $b))
T

Quelltext:

(defun free (expr var)
  (cond ((alike1 expr var) nil)
        ((atom expr) t)
        (t
         (and (consp (car expr))
              (free (caar expr) var)
              (freel (cdr expr) var)))))

Funktion: freel l var

Testet, ob die Elemente der Liste l frei von dem Argument var sind. Das Argument var kann ein Symbol oder ein beliebiger kMaxima-Ausdruck sein.

Siehe auch die Funktion free.

Quelltext:

(defun freel (l var)
  (do ((l l (cdr l)))
      ((null l) t)
    (when (not (free (car l) var)) (return nil))))

[ << ] [ >> ]           [Top] [Contents] [Index] [ ? ]

This document was generated by Dieter Kaiser on Dezember, 13 2011 using texi2html 1.76.