Kommen wir zu einer weiteren Eigentümlichkeit von Lisp,
nämlich
(c?r). Versuchen Sie nicht, diesen
Befehl einzugeben - so gibt es ihn nämlich gar nicht. Das
Fragezeichen ist einfach Stellvertreter für ein 'a'
oder ein 'd' oder zwei 'a' oder zwei 'd' oder für 'ad'
oder 'da' oder ... Der Befehl kann also
(car) oder
(cdr) oder
(caar) oder
(cddr) oder
(cadr) oder
(cdar) heißen. Er kann übrigens
auch
(caaar) oder
(cdadar) heißen.
Was für ein Quatsch, werden Sie jetzt denken, es kann
wahrscheinlich auch noch
(caaddadadddaddaaaaar)
heißen. Nein - 4 a oder d oder gemischtes Doppel - mehr
geht nicht. Kann man damit auch etwas anfangen? Kann man!
(car) gibt das erste Element einer Liste zurück:
(car '(1 2 3 4 5)) => 1
(cdr) gibt genau das zurück, was
(car) nicht
zurückgibt, nämlich die Liste ohne das erste Element.
(cdr '(1 2 3 4 5)) => (2 3 4 5)
Auch hier gilt wieder, daß die Befehle nicht symmetrisch
angeordnet sind. Es ist also nicht ganz so, das
(car)
das erste Element zurückgibt und
(cdr) die anderen.
Sie haben doch den feinen Unterschied bemerkt -
(car)
gibt ein Atom zurück und
(cdr) eine Liste. Nehmen
wir an, wir haben es mit einer verschachtelten Liste zu tun:
(setq verschachtelte-liste
'((a b)(c d e)(f)g(h(i j)))
)
Wenn wir das
a haben möchten, müssen wir also
(car(car verschachtelte-liste)) eingeben. Das können
wir aber abkürzen mit
(caar verschachtelte-liste).
(caar ...) ist also das gleiche wie
(car(car ...)),
und (caaar ...) ist das gleiche wie
(car(car(car ...))).
(caaar) läßt sich aber natürlich nur anwenden, wenn
die Verschachtelung der Liste auch tief genug ist. Das gilt
natürlich für alle
(c?r)-Funktionen
gleichermassen.
Schwieriger wird es, wenn wir z.B. auf das
e zugreifen
möchten. Bauen wir es langsam auf:
(cdr verschachtelte-liste)
=> ((C D E)(F)G(H(I J)))
(cadr verschachtelte-liste)
=> (C D E)
(cdadr verschachtelte-liste)
=> (D E)
(cddadr verschachtelte-liste)
=> (E)
Jetzt haben wir es fast - wir wollen ja nicht eine Liste,
sondern das Atom selbst. Und schon sind wir an der
4-Buchstaben-Grenze, es geht also nur noch so:
(car(cddadr verschachtelte-liste)) => E
So ganz einfach war das jetzt nicht. Machen wir uns
Folgendes klar: Mit jedem a in
(c?r) verschwindet
ein Klammerpaar und die anderen Elemente der gleichen
Verschachtelungs-Ebene, mit jedem d verschwindet ein
Element. Noch ein Beispiel:
(setq andere-liste
'(15(23 11(49)8)30(74 12(45 13(19))64)52)
)
(car andere-liste) gibt uns die 15 zurück, das
äußere Klammerpaar ist verschwunden.
(cdr andere-liste)
gibt die ganze Liste zurück, es fehlt lediglich das erste
Element, nämlich die 15:
(((23 11(49)8)30(74 12(45 13(19))64)52))
Wenn wir das erste Element des zweiten Elements (die 23)
haben wollen, dann müssen wir mit
(caadr) zugreifen.
Dies sei noch einmal in Stufen dargestellt.
(cdr andere-liste)
=> ((23 11(49)8)30(74 12(45 13(19))64)52))
(cadr andere-liste)
=> (23 11(49)8)
;äußere Klammer verschwindet
(caadr andere-liste)
=> 23
;äußere Klammer verschwindet
Es ist sicherlich sinnvoll, wenn Sie diese Art des
Listenzugriffs noch ein bißchen üben, um einige Sicherheit
bei der Anwendung von
(c?r) zu erlangen. Es gibt aber
noch eine weitere Methode, ein beliebiges Element aus einer
Liste zu extrahieren, nämlich mit der Funktion
(nth).
Diese Funktion wird z.B. so aufgerufen:
(setq farben'("rot" "grün" "blau" "gelb"))
(nth 2 farben) => "blau"
Beachten Sie bitte, daß bei der Verwendung von
(nth) die
Zählung bei 0 beginnt. "rot" bekommen Sie also mit
(nth 0 farben), "grün" mit 1 usw. In dieser Hinsicht
ist AutoLISP leider nicht ganz einheitlich, da bei anderen
Befehlen die Zählung bei 1 beginnt. Die Funktion
(nth)
mag auf den ersten Blick einfacher aussehen als
(c?r),
man kann mit ihr aber keine direkten Zugriffe auf verschachtelte
Listen realisieren wie mit
(c?r), sondern muß in diesem
Fall die Funktion mehrfach anwenden.
Zum Schluß soll auch die Funktion
(last) nicht unerwähnt
bleiben, mit der Sie auf das letzte Element einer Liste zugreifen
können, unabhängig davon, wie lang die Liste ist.
(setq farben'("rot" "blau" "grün" "gelb"))
(last farben) => "gelb"
Wie bereits kurz erwähnt, gibt es in AutoLISP keine Funktion,
mit der man ein Element aus einer Liste entfernen kann. Das
geht natürlich trotzdem, allerdings nur über Umwege. Allerdings
bietet AutoLISP noch die Funktion
(subst), mit der man
Elemente in einer Liste ersetzen kann.
(subst) wird mit
drei Argumenten aufgerufen, und zwar:
- das neue Element
- das alte Element
- die Liste
Ein Aufruf kann also z.B. so aussehen:
(setq farben'("rot" "blau" "grün" "gelb"))
(subst "lila" "grün" farben)
=> ("rot" "blau" "lila" "gelb")
Es sei hier noch einmal daraufhingewiesen, daß alle diese
Funktionen zur Listenbearbeitung die Listen selbst nicht
verändern. Wenn wir also nach diesem Beispiel (nth 2 farben)
eingeben, erhalten wir immer noch "grün" als Rückgabe. Dieser
Unterschied zwischen Manipulation der Rückgabe und Manipulation
der Daten ist so wichtig, daß wir uns noch ein wenig damit
befassen sollten, und zwar im nächsten Kapitel.
Übungsaufgaben
-
-