[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
3.1 Makros | ||
3.2 Allgemeine Hilfsfunktionen | ||
3.3 Testfunktionen | ||
3.4 Syntax der Bezeichner | ||
3.5 Funktionen für Ausdrücke |
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
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*
3.1.1 Allgemeine Makros | ||
3.1.2 Die Makros defun-prop und defmspec | ||
3.1.3 Das Makro defmvar | ||
3.1.4 Das Makro errset |
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
Das Makro ncons
macht das Argument x zum einzigen Element einer
Liste.
Beispiel:
* (ncons 'a) (A)
Quelltext:
(defmacro ncons (x) `(cons ,x nil))
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))
Das Makro implementiert eine while
-Schleife.
Quelltext:
(defmacro while (condition &rest body) `(do () ((not ,condition)) ,@body))
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
defun-prop
und defmspec
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)))
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] | [ ? ] |
defmvar
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.
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] | [ ? ] |
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.
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.1 Funktionen für die Eigenschaftsliste | ||
3.2.2 Informationslisten |
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
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
.
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)))
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))
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)))
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] | [ ? ] |
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.
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.1 Allgemeine Testfunktionen | ||
3.3.2 Teste kMaxima-Ausdrücke | ||
3.3.3 Teste kMaxima-Zahlen | ||
3.3.4 Teste Symbole mit Eigenschaften |
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
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))
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))
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))))
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.
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] | [ ? ] |
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.
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)))
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)))
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)))
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)))
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)))
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] | [ ? ] |
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)))
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)))
Testet, ob das Argument x eine große Gleitkommazahl ist.
Quelltext:
(defun bigfloatp (x) (and (consp x) (consp (car x)) (eq (caar x) 'bigfloat)))
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)))))
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)))
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))))))
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] | [ ? ] |
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))
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.1 Konvertierung zwischen Groß- und Kleinschreibung | ||
3.4.2 Zerlegen von Symbolen und Zeichenketten | ||
3.4.3 Alias und Reversealias | ||
3.4.4 Verb- und Substantivform |
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
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.
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))))
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))))
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] | [ ? ] |
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.
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)))
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)))
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] | [ ? ] |
Standardwert: ((mlist simp))
Liste der Symbole, die mit der Funktion $alias
einen Alias-Namen
erhalten haben.
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)))
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))))))))
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)))))
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)))
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] | [ ? ] |
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
.
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))))))
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)))
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) '(#\$ #\%)))))
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.1 Operatoren und Argumente holen | ||
3.5.2 Vergleiche Ausdrücke |
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
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)))
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] | [ ? ] |
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.
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)))))))
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))))
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))))
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)))))
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.