Der Autor
Dr. Karl Sarnow
wird Sie mit dieser Serie in die Welt der kĂŒnstlichen Intelligenz einfĂŒhren.
Er studierte Physik an der TU Hannover und unterrichtet zur Zeit an einem Gymnasium die FĂ€cher Mathematik, Physik und Informatik.
Anfang 1986 stieg er auf den ST um und kommuniziert mit ihm in allen nur erdenklichen Sprachen. Seine bevorzugten Programmiersprachen sind C, LISP und Prolog.
Zum Geleit
Dieser Artikel ist der erste in einer Reihe von AufsĂ€tzen, in denen ich Ihnen Probleme und Verfahrensweisen, die im Bereich der kĂŒnstlichen Intelligenz vorliegen, nahebringen möchte. Dabei werde ich mich bemĂŒhen, die beiden aktuellen Sprachen der KI â LISP und PROLOG - in gleicher Weise zu berĂŒcksichtigen. Da beide Sprachen im Public-Domain-Service der ST-Computer-Redaktion vorliegen, sollte es dem Leser nicht schwerfallen, diesem Kurs zu folgen. Ăbrigens hat jeder ST-Besitzer ja schon von Haus aus die ausgezeichnete Version einer Kl-Sprache mitbekommen: Die (viel zu wenig beachtete Logo-Version von Digital Research, die ich bei dieser Gelegenheit gerne aufwerten möchte. LOGO ist nicht nur die Turtle-Sprache fĂŒr Kinder. Als LISP-Derivat ist LOGO ohne Schwierigkeiten in der Lage, das zu vollbringen, was LISP kann. Deshalb werde ich die entsprechende LOGO-Variante ebenfalls erlĂ€utern. Jeder Kurs ist einem Schwerpunkt gewidmet und behandelt die fĂŒr das entsprechende Thema geeigneten Funktionen (LISP, LOGO) bzw. PrĂ€dikate (PROLOG). FĂŒr eine Ăbersicht ĂŒber LISP und PROLOG und die allgemeinen Anwendungsgebiete der KI sei auf meine bisher in dieser Zeitschrift erschienenen Artikel verwiesen (Heft Nr. 1/86 und 3/86). NatĂŒrlich wird es sich nicht vermeiden lassen, daĂ das eine oder andere Thema vorrangig in einer der drei Sprachen behandelt wird und die anderen Sprachen etwas zurĂŒcktreten. Ich möchte jedoch den Ăberblick ĂŒber die Methoden der KI von der Einengung der jeweils verwendeten Sprache befreien und andererseits die spezifischen Eigenschaften der jeweiligen Sprache erhalten.
Atome und Listen als Datenelemente
Bei Problemen der kĂŒnstlichen Intelligenz tritt die Rechenfertigkeit hinter der FĂ€higkeit der Symbolmanipulation zurĂŒck. Logischerweise bedient man sich hierzu anderer Datenstrukturen als fĂŒr die Bearbeitung arithmetischer Probleme. Die beiden Datentypen, mit denen wir uns hauptsĂ€chlich beschĂ€ftigen, sind Atome und Listen (einzige Ausnahme: Objekte in XLISP, siehe Literaturliste 2. Atome (gr.: atomos, unteilbar) sind Datenelemente, die nicht weiter strukturiert sind und folglich auch nicht in kleinere Bestandteile zerlegt werden können. Dies können symbolische Namen sein (hallo, auto, champagner, hexamethylentetramin, ...) oder Zahlen. Im letzten Fall spricht man von numerischen Atomen.
Listen sind im einfachsten Fall nicht anders als miteinander verbundene Atome. In LISP werden die einzelnen Elemente einer Liste von runden Klammern eingeschlossen, in PROLOG und LOGO von eckigen. Also ist
(hallo auto 3.141)
bzw.
[hallo, auto, 3.141]
eine Liste in LISP, LOGO bzw. PROLOG, welche die Atome hallo, auto und 3.141 enthÀlt. Allerdings können Listen wiederum Listen als Elemente enthalten [(Rekursion, ick hör dir trapsen!)]. Ein etwas sinnvolleres Beispiel wÀre (LISP-Notation):
(rufname (vornamel vorname2 vorname3) name)
Auf die natĂŒrliche Intelligenz des Lesers vertrauend, verzichte ich auf die PROLOG- und LOGO-Schreibweise.
In dieser Liste werden die Patennamen als Unterliste gefĂŒhrt. Die Liste selbst besteht also aus drei Elementen, den Atomen rufname und name sowie der Liste mit den drei Patennamen. LISP schieĂt in Sachen Listenbehandlung den Vogel ab, weil der Interpreter jeden Befehl in Listenform erwartet.
Die einfachsten Beispiele fĂŒr Listenverarbeitung stammen deshalb in LISP aus dem Bereich der Arithmetik - ein Indiz fĂŒr den Wahrheitsgehalt der Vermutung, daĂ reine RechenfĂ€higkeit und Intelligenz wenig korreliert sind.
Gibt man in LISP die folgende Liste ein, interpretiert sie der Interpreter als einen auszufĂŒhrenden Befehl und gibt prompt das Ergebnis der AusfĂŒhrung bekannt (fett: Benutzereingabe, kursiv: Antwort des Interpreters).
(+ 1 2)
3
Da XLISP ein eval_LISP ist (siehe Literaturliste 2), erkennt das System beim Versuch, die Liste zu evaluieren, daĂ das erste Element der Liste ein Atom ist, das die Bedeutung einer im System eingebauten Funktion hat, und fĂŒhrt die Funktionsberechnung durch. Solche im System eingebauten Funktionen tragen die Bezeichnung Primitiv. Am Beispiel der Addition in LISP kann man auch einen Vorteil der Liste gegenĂŒber anderen Datenstrukturen erkennen. So erlaubt LISP mehr als 2 Argumente bei allen arithmetischen Operationen:
(+ 1 2 3 4 5)
15
(â
2 4 3)
24
Listen in den Kl-Sprachen haben zudem den Vorteil, daà ihre Elemente typenlos sind (im Gegensatz zu PASCAL oder C). Beispielsweise werden die folgenden beiden Listen gleichwertig als EintrÀge einer Gehaltsliste akzeptiert:
(schmidt emil 1200.50)
(meier (hans georg gustav) 3179.20)
In allen drei Sprachen werden ĂŒbrigens die Rechenoperationen in PrĂ€fix-Notation angegeben. Nur LOGO als âAnfĂ€ngerspracheâ hat hier dem traditionellen Infix-Denken Tribut gezollt und erlaubt zusĂ€tzlich noch die Infix-Notation fĂŒr arithmetische Operationen. Die PrĂ€fix-Notation hat den Vorteil, daĂ der Operator immer an der gleichen Stelle steht, unabhĂ€ngig von der Anzahl der Argumente der Operation. Das Umdenken ist zwar lĂ€stig, doch wenn die natĂŒrliche Intelligenz beim Umgang mit der kĂŒnstlichen Intelligenz etwas abbekommt, so ist das ein nicht nur erwĂŒnschter, sondern beabsichtigter Nebeneffekt.
Zugriff auf Listenelemente
Der Zugriff auf die Listenelemente ist natĂŒrlich das A und O der Programmierung in unseren drei Lieblingssprachen. Tab. 1 faĂt die elementaren Zugriffsmöglichkeiten in diesen Sprachen zusammen. VerstĂ€ndlicherweise ergibt sich in PROLOG die deutlichste Abweichung von LISP, weil der Zugriff auf die Fakten der Datenbank nur ĂŒber den Unifizierungsmechanismus (siehe Literaturliste 3) erfolgen kann. Die PrĂ€dikate nth/3 und cons/1 in Tab. lc sind benutzerdefiniert und sollten dem jeweiligen Verwendungszweck angepaĂt werden.
Die Assoziationsliste
Eine besondere Form von Liste ist in LISP die sogenannte Assoziationsliste (LOGO: Property Liste). Sie ermöglicht das Speichern von miteinander verbundenen Elementen. Weiter unten benutzen wir eine Assoziationsliste, um einen deutschsprachigen Simpeltext in ein holpriges Englisch zu ĂŒbersetzen. Man speichert dann lediglich in einer Assoziationsliste die deutsch-englischen Assoziationen ab, also im unten aufgefĂŒhrten Beispiel:
((dies this) (satz sentence) (ist is) (ein a))
Das erste Element einer Assoziationssubliste wird SchlĂŒssel genannt (also: dies, satz, ist, ein). Verschiedene Listenfunktionen in LISP erlauben ein sehr effektives Arbeiten speziell mit dieser Listenform.
Funktion |
AusfĂŒhrung in LISP |
Bindung der Liste (a, b, c) an das Symbol liste |
(setq liste â(a, b, c)) oder (setq liste (list âa âb âc)) |
Ausgabe des 1. Elementes a |
(car liste) |
Ausgabe der Restliste (b, c) |
(cdr liste) |
Ausgabe des 2. Elementes b |
(car (cdr liste)) oder (cadr liste) |
Ausgabe des n. Elementes |
(nth n liste) |
EinfĂŒgen eines neuen Elementes x in die Liste. Die neue Liste ist (x, a, b, c) |
(cons x liste) |
AneinanderhÀngen zweier Listen. Ergibt (a, b, c, d, e, f) |
(append â(a, b, c) â(d e, f)) |
Tabelle 1a: Elementare Listenoperationen in LISP
BĂ€ume als spezielle Listen
Wir haben schon gesehen, daà die Elemente von Listen wiederum Listen sein können. Diese Datenstruktur nennt man besser einen Baum. Zur Veranschaulichung soll uns die folgende Liste dienen:
(k1 (k2 b1 b2) (k3 (k4 b3 b4) (k5 b5
(k6 b6 b7))))
Den zugehörigen Baum zeigt Abb. 1. Es bedeuten hierin k1 - k6 die Knoten des Baumes, b1 - b7 die BlÀtter des Baumes. Kenner werden einen sogenannten BinÀrbaum wiedererkennen; solche, die es werden wollen, lesen bei Literaturliste 4 nach, k1 ist hier die Wurzel des binÀren Beispielbaumes.
Funktionen in LISP und LOGO
Wir verlassen nun erst einmal den gemeinsamen Teil und kĂŒmmern uns speziell um die Organisation eines LISP-bzw. LOGO-Programmes. PROLOG ist eine relationale Sprache, in der das Programm aus Fakten und miteinander verknĂŒpften Klauseln besteht, wĂ€hrend LISP und LOGO als funktionale Sprachen ihr Ergebnis aus dem sequentiellen Aufruf von Funktionen erhalten. Wie in Pascal gibt es auch LISP- und LOGO-Programmteile, die zwar behandelt werden wie Funktionen, aber keinen Funktionswert liefern. Sie heiĂen (wie in Pascal auch) Prozeduren. Allgemein gilt, daĂ Prozeduren dann keine Funktionen sind, wenn sie Nebeneffekte zeigen. SelbstverstĂ€ndlich gibt es auch in LISP und LOGO standardmĂ€Ăig vorgesehene Funktionen und Prozeduren; sie heiĂen Primitive, setq ist ein Beispiel fĂŒr eine LISP-Prozedur, die keine Funktion ist, weil sie als Nebeneffekt einen Wert (2. Argument) an ein Symbol (1. Argument) bindet. Die Primitive car und cdr in Tab. la sind natĂŒrlich Funktionen, die ein entsprechendes Atom bzw. eine Liste als Funktionswert zurĂŒckgeben. Und da sie ihr Argument nicht verĂ€ndern, haben sie auch keine Nebeneffekte. Tab. 2 zeigt eine Zusammenfassung aller Listenprimitive in XLISP mit Beispielen. Um Ăbersichtlichkeit zu wahren, werde ich hier lediglich die LlSP-Schreibweise erwĂ€hnen. Anhand der Tab. 1 sollte der Leser in der Lage sein, die entsprechende LOGO-Schreibweise zu erarbeiten. Die schon in Tab. 1 erwĂ€hnten Primitive car, cdr und cons bilden so etwas wie ein Funktions-Umkehrfunktionspaar. D. h., es gilt die IdentitĂ€t:
(cons (car liste) (cdr liste)) = liste
Mit cons wird also eine durch car und cdr aufgetrennte Liste wieder zusammengefĂŒgt. Bitte erinnern Sie sich, daĂ in einer Liste nicht nur Atome, sondern auch Listen als Elemente stehen können. So ist z. B. ((a b) (c d)) eine Liste, die aus zwei Elementen besteht: der Liste (a b) und der Liste (c d). Folglich ergibt (car '((a b) (c d))) den Funktionswert (a b), eine Liste als erstes Element, (cdr '((a b) (c d))) liefert dann logischerweise ((c d)), die Restliste, die die Liste (c d) als einziges Element enthĂ€lt. FĂŒr die in Tabelle 2 aufgefĂŒhrten Funktionen gibt es noch Optionen, deren Besprechung den Rahmen dieser EinfĂŒhrung sprengen wĂŒrde. Der Leser sei hier auf das XLISP-Manual verwiesen.
Funktion |
AusfĂŒhrung in LOGO |
Bindung der Liste [A, B, C] an das Symbol LISTE |
MAKE "LISTE [A, B, C] |
Ausgabe des 1. Elementes A, |
FIRST :LISTE |
Ausgabe der Restliste [B, C] |
BUTFIRST :LISTE |
Ausgabe des n. Elementes |
ITEM n :LISTE |
EinfĂŒgen eines neuen Elementes X in die Liste. Die neue Liste ist [X, A, B, C] |
MAKE "LISTE (FPUT "X, :LISTE) |
Tabelle 1b: Elementare Listenoperationen in LOGO
Funktion |
AusfĂŒhrung in PROLOG |
Nimmt das Fakt, das [a, b, c] eine Liste ist in die Datenbank auf. |
assert(liste([a,b,c]). |
Ausgabe des 1. Elementes der Liste in der Datenbank a |
liste([Erstes1]). |
Ausgabe der Restliste [b, c] |
liste([... |
Ausgabe des 2. Elementes b |
liste([...,Zweites |
Ausgabe des n. Elementes |
liste(X),nth(n,X,Element). mit: nth(1,[Kopf |
EinfĂŒgen eines neuen Elementes x in die Liste in der Datenbasis. Die neue Liste ist [x, a, b, c] |
cons(x). mit cons(X):â liste(Y),assert(liste([X |
AneinanderfĂŒgen zweier Listen. Ergibt Liste = [a, b, c, d, e, f] |
append([a, b, c],[d, e, f], Liste). |
Tabelle 1c: Elementare Listenoperationen in PROLOG
Abb. 1: BinÀrer Beispielbaum
Evaluierung von LISP-Termen
ErfahrungsgemÀà bereitet AnfĂ€ngern die Evaluierung von LISP-Termen groĂe Schwierigkeiten. Deshalb möchte ich die in Literaturliste 2 recht kurz geratene EinfĂŒhrung hier ergĂ€nzen. Generell versucht LISP (genauer gesagt ein eval-Lisp), den Wert eines Terms zu erfahren, bevor es ihn weiterverarbeitet. Zur Anschauung betrachte man den XLISP-Dialog in Abb. 2. In der ersten Zeile wird das Atom A an den Wert 1 gebunden. Da ein Atom (eine Zahl ist ein numerisches Atom) zu sich selbst evaluiert, ist in der Anweisung kein Apostroph fĂŒr 1 erforderlich. Eigentlich mĂŒĂte das Symbol A mit einem Apostroph eingegeben werden, um dem Interpreter zu verdeutlichen, daĂ das Symbol A als unevaluiertes Atom verwendet werden soll. Dies ist nicht erforderlich, weil meist eine Bindung ohnehin nur an ein Atom erfolgt und LISP deshalb vorsorglich das erste Argument mit einem Apostroph versieht, setq ist schlieĂlich nichts anders als die Kurzform von set quote. (setq a 1) ist also Ă€quivalent zu (set âa 1). In der zweiten Anweisung wird schlieĂlich das Atom B an die Liste (+ a 1) gebunden. Dies ist zwar die Anweisung, die Summe von a und 1 zu berechnen, da sie aber in der setq Anweisung quotiert wird, wird sie nicht ausgefĂŒhrt. Wachsame haben vielleicht bemerkt, daĂ hier bereits die in Pascal, C, Basic & Co. streng durchgefĂŒhrte Trennung von Programm und Daten verwischt. Hier dient eine Programmanweisung (addiere den Wert von a und 1) als Wert. LĂ€Ăt man die Quotierung fĂŒr das zweite Argument weg, dann wird die Evaluierung des zweiten Terms durchgefĂŒhrt. D. h., die Summe von A und 1 wird erst berechnet und dann das Ergebnis an C gefunden (dritte Anweisung). Das Ergebnis der vierten Anweisung zu verstehen, dĂŒrfte nun keine Schwierigkeiten bereiten: A evaluiert zu 1. C evaluiert zu 2 und die Summe ist 3. Wer nun in der fĂŒnften Anweisung (+ a b) ein vernĂŒnftiges Ergebnis erwartet, hat zu hohe Erwartungen an den XLISP-Interpreter. SelbstverstĂ€ndlich evaluiert XLISP den Term zu ( +1 (+ A 1)). aber die Evaluierung wird nicht rekursiv bis zur letzten Stufe durchgefĂŒhrt. sondern stoppt hier. Da die Addition zwei numerische Atome verknĂŒpfen will, (+ A 1) aber eine Liste darstellt, ist nun die Fehlermeldung bad argument type zu erwarten. Sorgt man mit eval b jedoch ausdrĂŒcklich fĂŒr eine Evaluierung des Termes 3. dann wird in der Tat die korrekte Summe ermittelt (sechste Anweisung):
(+ a (eval b)) â (+ a (+ a 1)) â
(+ 1 2) - 3
Einige einfache Anwendungen
Ungeachtet der Tatsache, daĂ LISP keine Sprache ist, in der man bevorzugt rechenintensive VorgĂ€nge bearbeitet, betrachten wir als einfachstes Beispiel die Berechnung einer Wertetabelle. Dies lĂ€Ăt sich folgendermaĂen erreichen:
(setq argumente â(0.0 0.785398 1.04719 1.57079 3.14159))
(setq wertetabelle (mapcar sin argumente))
Diese zwei Zeilen berechnen den Sinus von 0,/4,ir/3,V2 und n . Die Funktionswerte findet man anschlieĂend in der Wertetabelle wieder:
wertetabelle
(0.000000 0.707106 0.866021
1.000000 0.000020)
Ein weiteres einfaches Beispiel unter Verwendung der Listenfunktionen ist die Ăbersetzung eines deutschsprachigen Texten in pitching english. D. h., man ĂŒbersetzt den Text wortweise und erhĂ€lt ein mehr oder weniger brauchbares Konglomerat englischer Worte, die im Idealfall einen lesbaren Satz bilden. Dazu stellt man sich zunĂ€chst ein Lexikon in Form einer Assoziationsliste zusammen, deren erste Element jeweils das deutsche Wort und dessen zweites Element das zugehörige englische Wort darstellen. Dann lĂ€Ăt man die Assoziationsliste die entsprechenden Substitutionen durchfĂŒhren und entfernt anschlieĂend die störenden Klammern aus dem Text:
(setq deutsch_englisch '((dies this)
(satz sentence) (ein a) (ist is)) ((DIES THIS) (SATZ SENTENCE)
(EIN A) (IST IS))
(setq deutsch '(dies ist ein satz))
(DIES IST EIN SATZ)
(setq englisch (sublis deutsch_englisch
deutsch))
((THIS) (IS) (A) (SENTENCE))
(setq englisch (mapcar car englisch))
(THIS IS A SENTENCE)
Die letzten beiden Zeilen lassen sich natĂŒrlich noch zu einer zusammenfassen:
(DIES IST EIN SA TZ)
(setq englisch (mapcar car(sublis
deutsch__englisch deutsch)))
(THIS IS A SENTENCE)
Die eigentlich interessanten Anwendungen erhĂ€lt man allerdings erst, wenn man seine eigenen Funktionen definieren kann. Dazu kommen wir aber erst in der nĂ€chsten Folge. Dann nĂ€mlich geht es um die Definition von Funktionen und das LAMBDA-Konzept. Wie Sie sehen, bleiben wir also noch ein wenig im LISP/LOGO-Sprachraum. Erst wenn wir die PrĂ€dikatsfunktionen besprechen, werden wir unseren Blick wieder stĂ€rker in Richtung PROLOG Lenken. SchlieĂlich ist PROLOG die Sprache zur Verarbeitung logischer PrĂ€dikate.
[1] Sarnow, K. EinfĂŒhrung in die kĂŒnstliche Intelligenz. ST-Computer 11/86.
[2] Sarnow, K. XLISP Review. ST-Computer 1/87
[3] Sarnow, K. TOY-PROLOG Review. ST-Computer 2/87.
[4] Wirth, Niklaus. Algorithmen und Datenstrukturen. B. G. Teubner, 1975.
append
: Siehe Tabelle 1a.
assoc
: Findet einen Term in einer Assoziationsliste. Beispiel:
(setq arbeiter â((name emil) (gehalt 1526.65)))
(assoc âgehalt arbeiter)
(GEHA L T 1526.650000)
car
: Siehe Tabelle 1a.
cdr
: Siehe Tabelle 1a.
cxxr
: xx bedeutet eine beliebige Kombination von a und d. z. B. cadr oder cdar oder cddr oder caar. Siehe Tabelle 1a.
cxxxr
: Siehe cxxr und Tabelle 1a.
cxxxxr
: Siehe cxxr und Tabelle 1a.
cons
: Siehe Tabelle 1a.
last
: Ergibt die Liste, welches das letzte Element enthÀlt. Beispiel:
(last â(a b c))
(c)
length
: Gibt als Funktionswert die Anzahl der in der Liste enthaltenen Elemente an. Beispiel:
(length â(a b (c d)))
3
list
: Der Funktionswert ist eine Liste der Argumente. Beispiel:
(list âa âb â(c d))
(a b (c d))
mapc
: Wendet die Funktion (1. Argument) nacheinander auf die Listen der Argumentwerte (2. - n. Argument, eine Liste je Argument der Funktion) an. Als Funktionwert wird die erste Liste von Argumenten ausgegeben (2. Argument von mapc). Beispiel:
(mapc + â(1 2 3) â(4 5 6)))
(1 2 3)
Man beachte, daĂ von der Summation nichts bemerkt wird, da die Funktion + (Addition) nebeneffektfrei ist und die Ergebnisse einfach vergessen werden. Diese Listenfunktion sollte deshalb nur bei Funktionen mit Nebeneffekt angewendet werden. Beispiel:
(mapc (lambda (x y) (prinl (+ x y))) â(1 2 3) â(4 5 6))
579(1 2 3)
Uber die Bedeutung von lambda spÀter.
mapcar
: Wie mapc, allerdings wird hier als Funktionswert die Liste der Funktionswerte zurĂŒckgegeben. Beispiel:
(mapcar + â(1 2 3) â(4 5 6))
(5 7 9)
mapl
: Wie mapc, wendet die Funktion aber auf die cdr der Argumentlisten an. Beispiel:
(mapl length â(a b c))
(a b c)
Man beachte auch hier, daĂ die Funktion Nebeneffekte haben muĂ, um eine Wirkung zu zeigen.
maplist
: Wie mapcar, wendet die Funktion aber au die cdr der Argumentlisten an. Beispiel:
(maplist length â(a b c))
(3 2 1)
Zuerst ist die Argumentliste (a b c) und deren LĂ€nge 3. Der cdr dieser Liste ist (b c), die LĂ€nge 2. Der cdr dieser Liste ist (c), die LĂ€nge 1. Dann bricht maplist ab, weil der folgende cdr NIL ist.
member
: Findet einen Ausdruck in einer Liste und gibt die Restliste zurĂŒck. Beispiel:
(member âb â(a b c))
(b c)
nth
: Siehe Tabelle 1a.
nthcdr
: Gibt den n-ten cdr einer Liste zurĂŒck. N = 0 ergibt die Originallfte. Beispiel:
(nthcdr 2 â(a b c d e f))
(c d e f)
remove
: Entfernt einen Term aus einer Liste. Beispiel:
(remove âb â(a b c))
(a c)
reverse
: Kehrt eine Liste in der Reihenfolge ihrer Elemente um. Beispiel:
(reverse â(a b c))
(c b a)
sublis
: Ersetze mit Hilfe einer Assoziationsliste. Beispiel:
(sublis â((halli hallo)) '(aber halb))
(ABER (HALLO))
subst
: Ersetzt LISP Terme. Beispiel:
(subst âdemo âb â(a b c))
(a demo c)
Tabelle 2a: Listenfunktionen in XLISP
delete
: Löscht einen Term aus einer Liste. Beispiel:
(setq liste â(a b c))
(A B C)
(delete liste âb)
(A C)
nonc
: Vereinigt zwei Listen zu einer (physisch). Beispiel:
(setq liste 1 â(a b c))
(A B C)
(setq liste2 â(d e f))
(D E F)
(nonc liste 1 liste2)
(A B C D E F)
liste 1
(A B C D E F)
liste 2
(D E F)
rplaca
: Ersetzt den car einer Liste. Beispiel:
(setq liste â(a b c))
(A B C)
(rplaca liste âb)
(B B C) liste
(B B C)
rplacd
: Ersetzt den cdr einer Liste. Beispiel:
(setq liste â(a b c))
(A B C)
(rplacd liste â(d e))
(A D E) liste
(A D E)
Tabelle 2b: Listenprozeduren in XLISP (destruktiv)
> (setq a 1) <-------------------A wird an den Wert 1 gebunden
1
> (setq b â(+ a 1)) <-----------B wird an die Liste (+ A 1) gebunden
(+A 1)
> (setq c (+ a 1)) <------------C wird an den Wert der evaluierten
2 Liste (+ A 1) gebunden, d. h. an 2.
> (+ ac) >----------------------A evaluiert zu 1 C evaluiert zu 2,
3 die Summe beider ergibt 3.
> (+ a b)
error: bad argumenttype - (+ A1) B evaluiert zu - AI), das ist der
1: > falsche Argumenttyp fĂŒr eine Addition.
> (+ a (eval b)) >--------------Eval be. = _o zu (+ A1), dies wird
3 zu 2 evaluiert. A wird zu 1 evaluiert,
> die Summe ergibt 3.
Abb. 2: Protokoll eines XLISP Dialoges zum Problem der Evaluierung