Ein paar Worte vorabHome   Letzte MeldungenNews   Index der Kapitel und der besprochenen FunktionenIndex   Wer ich bin, warum ich diese Seiten mache, KontaktImpressum   Ich freue mich über jeden Eintrag im Gästebuch!Gästebuch   Einige Links zu anderen AutoLisp-SeitenLinks   Copyrights und DisclaimerRechts
Hier können die kompletten Seiten als ZIP-File heruntergeladen werden!

Berechnen von arithmetischen Ausdrücken in der Kommandozeile Sitz!Platz!Fass!
Das Verschachteln von Ausdrücken Alte Schachtel!
Das Speichern von Werten in Variablen Gebunkert
Verhindern der Evaluation mit Quote Bergbäche
Erzeugen von einfachen Listen in AutoLisp Brot,Eier,Käse
Einfache Funktionen zur Listenbearbeitung ...um die Wurst
Funktionen für den Zugriff auf Listenelemente Was ein Salat!
Über Haupt- und Nebeneffekte von Funktionen Schwer schuften
Das Definieren von eigenen Funktionen in AutoLisp Ostfriesischer...
Lokale Variablen und Funktionsargumente in AutoLisp Kondome!
Das Laden von Programmdateien in AutoLisp Banküberfall
Verzweigung in Funktionen aufgrund von Entscheidungen Wenn das Wort...
Zusammenfassen von Entscheidungen mit den Logik-Funktionen Ins Schweinderl
Mehrfach-Verzweigungen in AutoLisp mit Cond 3. Strasse links
Schleifen zum Steuern des Ablaufs in AutoLisp-Funktionen Wie im Fernsehen
Testfunktionen zum Steuern von Schleifen in AutoLisp Schwanger?
Gleichheitstests als Schleifenkriterium in AutoLisp Noch gleicher?
Zeichneketten-Bearbeitung in AutoLisp Rauchzeichen
Funktionen zur Konvertierung von Datentypen in AutoLisp Wasser zu Wein
Komplexere Funktionen für die Bearbeitung von Listen in AutoLisp Nicht arbeiten...
Das Erzeugen von anonymen Funktionen mit lambda Schwarze Kutte
Das Bearbeiten von Listenelementen mit foreach Jedem das Seine
Erzeugen und Verwenden von Assoziationslisten in AutoLisp Beim Psychiater
Zugriff auf Geometriedaten und Erzeugen von Geometrieelementen Ententanz
Der Umgang mit Auswahlsätzen in AutoLisp Jung gefreit, ...
Auswahl von AutoCAD-Zeichnungsgeometrie mit ssget Raffgierig!
Verändern von Zeichnungs-Geometrie mit entmod Flickschusterei
Das Erzeugen von Geometrie mit entmake Houdini
Über Programmierstile in AutoLisp, Teil 1 Emma
Über Programmierstile in AutoLisp, Teil 2 Sti(e)lblüten
Über Programmierstile in AutoLisp, Teil 3 Eingewickelt
Über Programmierstile in AutoLisp, Teil 4 Doofe Frisur?


Zum den Seiten für Fortgeschrittene

Zu den ActiveX-Seiten

Meine Private HP mit Fotos, Gedichten, Musik und Postkartenversand

Mein Online-Lexikon der Fotografie

Mein völlig abgedrehtes Reisebüro










Was kann man nun mit Listen anfangen? Nun - niemand will Ihnen den Mut nehmen, aber mit Ihrem jetzigen Wissensstand herzlich wenig. Lassen Sie uns daher einige Möglichkeit der Bearbeitung von Listen besprechen. Sie werden wahrscheinlich nicht auf Anhieb wissen, wieviele Elemente die Liste lispziger-allerlei aus dem letzten Kapitel enthält. Also nachzählen - oder:
(setq lispziger-allerlei
 '( 1 "Hemd" float 16.34 pi () (expt 10 3))
)

(length lispziger-allerlei) => 7
                  
Die Funktion (length) gibt die Länge einer Liste zurück, d.h. die Anzahl der Listenelemente. Unterlisten zählen als ein Element. Schön und gut - aber was kann man noch mit Listen machen? Denken Sie einen Moment nach und schreiben Sie einen Wunschzettel.

Der Wunschzettel könnte so aussehen:
  • Feststellen, ob ein bestimmtes Element in der Liste vorhanden ist
  • Ein neues Element in die Liste einfügen
  • Ein Element aus der Liste entfernen
  • Feststellen, ob Elemente doppelt vorkommen
  • die Liste alphabetisch sortieren
  • die Liste auf dem Drucker ausgeben
  • die Liste als Text in die Zeichnung einfügen


Und nun kommen die Antworten auf Ihren Wunschzettel, die wahrscheinlich erst einmal etwas ernüchternd wirken werden: Es gibt eine Funktion (member), die dazu dient, festzustellen, ob ein bestimmtes Element in einer Liste vorhanden ist. So wird sie benutzt:
(member "Hemd" lispziger-allerlei)
    => ("Hemd" FLOAT...usw.)

(member 'FLOAT lispziger-allerlei)
    => (FLOAT 16.34...usw)
                  
(member) gibt immer den Listenrest beginnend mit dem gesuchten Element zurück. Wenn das Element nicht enthalten ist, wird nil zurückgegeben. Vergessen Sie jedoch nicht, das gesuchte Element zu quoten, da LISP sonst versucht dieses zu evaluieren ("Hemd" ist ein Sonderfall, da es wegen der Anführungszeichen sowieso nicht evaluiert werden kann).

Sie können jederzeit ein neues Element vor den Anfang der Liste setzen - und zwar mit der Funktion (cons).
(cons 'neues_element lispziger-allerlei)
    => (NEUES_ELEMENT 1 "Hemd" usw.)
                  
Mit einem kleinen Umweg können Sie auch ein neues Element an das Ende der Liste anfügen. Dazu dient die Funktion (append). Diese Funktion kann allerdings nur zwei oder noch mehr Listen zu einer neuen Liste zusammenfügen, d.h. ein Aufruf in der Art (append vorhandene-Liste neues-element) ist zum Scheitern verurteilt. Wir müssen also auch noch die Funktion (list) zu Hilfe nehmen, mit der man eine Liste erzeugen kann. Zunächst zu (list):
(setq erzeugte-liste
  (list 'ein_element 'noch_ein_element)
) => (EIN-ELEMENT NOCH-EIN-ELEMENT)
                  
Beachten Sie, daß jetzt jedes Element einzeln gequotet werden muß. Wenn wir nun das Element neues_element am Ende von lispziger-allerlei einfügen wollen, müssen wir das so anstellen:
(append lispziger-allerlei (list 'neues_element))
                  
Lisp antwortet uns nun wunschgemäß mit der Rückgabe:
=> (1 "Hemd" FLOAT 16.34 PI () (EXPT 10 3) NEUES_ELEMENT)
                  
aber wenn wir jetzt !lispziger-allerlei eingeben, bekommen wir doch wieder nur die alte Version ausgegeben:
=> (1 "Hemd" FLOAT 16.34 PI () (EXPT 10 3))
                  
Ja richtig - da war doch was! Genau - wir müssen zwischen Rückgabe und Zuweisung eines Wertes an ein Symbol unterscheiden. Erst die Eingabe von
(setq lispziger-allerlei
  (append lispziger-allerlei
    (list 'neues_element)
  )
)
                  
verleiht der Sache endgültigen Charakter.

Das Entfernen eines Elements aus einer Liste ist in AutoLISP leider keine ganz einfache Angelegenheit. Es gibt weder eine direkte noch eine Umweg-Funktion. Man muß die ganze Liste unter Auslassung des zu entfernenden Elements in eine neue Liste umkopieren. Auch die Antwort auf diese Frage setzt ein fundiertes AutoLISP-Wissen voraus und kann erst später gelöst werden. Das Sortieren einer Liste setzt auf jeden Fall voraus, daß die Liste einen einheitlichen Datentyp enthält (also entweder Zahlen oder Zeichenketten).

Andere Datentypen lassen sich nicht (oder kaum) sinnvoll sortieren. In Erwägung zu ziehen wären noch Listen, die ausschließlich Listen enthalten. Diese wären dann sortierbar, wenn die Unterlisten ausschließlich Zahlen oder Zeichenketten enthielten. Solche Listen können z.B. geometrische Punkte enthalten, diese werden immer als Liste mit drei Zahlen (X-, Y- und Z-Koordinate) dargestellt.

Die Möglichkeit des Druckerzugriffs besteht in AutoLISP überhaupt nicht. AutoLISP gestattet keinerlei Hardware-Zugriffe außer dem Lesen und Schreiben von Dateien (in den neuesten Versionen noch etwas mehr, wie z.B. das Löschen). Diese Beschränkung läßt sich nicht umgehen - auch nicht durch noch so fundierte LISP-Kenntnisse.

Die Ausgabe von Listen in die Zeichnung (als Text) stellt einen Programmierer vor nicht allzu große Probleme. Uns fehlt zwar jetzt noch das notwendige Handwerkszeug, wir werden es aber bald behandeln und sollten dann eine solche Aufgabenstellung leicht lösen können.

Nun aber zurück zu den Befehlen zur direkten Bearbeitung von Listen. Wir haben (length) kennengelernt, mit dem man die Länge einer Liste ermitteln kann, ferner (cons) und (append). Mit (cons) kann man ein Element vor eine Liste setzen, und (append) fügt zwei oder noch mehr Listen zusammen. Wir sollten jetzt aber noch einmal auf (cons) eingehen, da es eine etwas komplexere Funktion ist. Wenn wir den folgenden Ausdruck eingeben:
(cons "gelb" '("rot" "grün" "blau"))
                  
dann sehen wir, daß im Normalfall das erste Argument ein Atom und das zweite eine Liste sein muß. Stopp! Der Begriff Atom ist doch bisher gar nicht gefallen. Ganz einfach - ein Atom ist etwas, wenn es keine Liste ist. Liste ist also das Gegenteil von Atom und umgekehrt. Eine Kleinigkeit stört aber doch wieder: Die leere Liste - nil - ist sowohl eine Liste als auch ein Atom. Wir haben also eine einzige Ausnahme, die die Regel aber doch nur bestätigt.

Die Funktion (append) verlangt als Argumente ausschließlich Listen. Jeder Versuch, ihr ein Atom unterzumogeln, endet mit einer Fehlermeldung. Bei (cons) ist das anders. Das erste Argument kann sowohl ein Atom als auch eine Liste sein. Im letzten Beispiel war es das Atom "gelb". Setzen wir als erstes Argument eine Liste, dann wird diese Liste als Unterliste an den Anfang gesetzt.
(cons '("lila" "gelb") '("rot" "grün" "blau"))
                  
ergibt also (("lila" "gelb")"rot" "grün" "blau"). Die Länge dieser so erzeugten Liste ist 4. Hätten wir einfach eine Liste mit den 5 Farben gewollt, dann hätten wir eben (append) bemühen müssen und nicht (cons). (cons) bietet aber noch eine andere Möglichkeit, die wir jetzt nur kurz erwähnen können. Wir werden später in einem eigenen Abschnitt darauf eingehen. Wenn bei (cons) das zweite Argument ein Atom ist, dann ...

Probieren wir es doch einfach aus:
(cons "rot" "grün") =>  ("rot" . "grün")
                  
Was da herausgekommen ist, nennt sich ein 'dotted pair' - ein gepunktetes Paar. Diese dotted pairs sind für viele tatsächlich ein so erfreulicher Anblick wie ein von Windpocken, Masern und der Beulenpest gleichzeitig heimgesuchtes Pärchen chinesischer Nackthunde. Und was das Dumme daran ist: Sie sind nicht etwa so selten wie sechs Richtige im Lotto - nein, fast die gesamte AutoCAD-Geometriedatenbank besteht aus dotted pairs. Warum sollten wir etwas gegen diese Dinger haben, werden Sie sich jetzt fragen. Antwort kommt sofort - versuchen Sie folgende Eingaben:
(cons 'a '(b . c))         =>   Fehlermeldung
(length '(a . b))          =>   ebenso
(append '(a . b)'(c . d))  =>   raten Sie mal...
                  
Es sind also keine Listen? Versuchen Sie es mit (listp). Das ist eine sogenannte Prädikatfunktion; sie testet, ob etwas eine Liste ist.
(listp '("rot" . "blau"))  => T
                  
T bedeutet hier soviel wie 'Ja' oder 'wahr' (T steht für "true", listp für 'list predicate'). Vielleicht noch eine Ausnahme, die gleichzeitig Liste und Atom ist? Nein, versprochen ist versprochen, außer nil gibt es keine Ausnahmen mehr. Sie können das auch testen, die Funktion heißt (atom). Sie sollte eigentlich (atomp) für 'atom predicate' heißen, daß p am Ende ist aber offensichtlich irgendwann irgendwo auf der Strecke geblieben.

Egal - wir stellen fest, es handelt sich bei den schwerkranken chinesischen Nackthunden nicht um Atome, sondern wirklich um Listen. Trotzdem versagen fast alle Listenbefehle an ihnen, und damit müssen wir leben.

Übrigens, wenn das Ergebnis einer Test- oder Prädikatfunktion negativ ausfällt, dann wird statt des T nicht etwa F (false) oder G (gelogen, gemogelt) oder so etwas ausgegeben, sondern nil. Die leere Liste muß also doch für einiges herhalten. Dazu später mehr...

Wir lassen alle diese hochinteressanten Fragen jetzt doch erst mal dahingestellt und befassen uns noch ein wenig mit (append) und (cons). Hüten Sie sich vor der Annahme, daß dies zwei ähnliche Funktionen sind, so etwa nach dem Motto: (cons) nehmen wir, wenn wir etwas vorne davorsetzen wollen, und (append) kommt dan dran, wenn wir etwas hinten ankleben wollen.

Das ist so falsch, wie es falscher nicht sein kann! (cons) fügt Elemente ein, und (append) verbindet zwei Listen. Wenn uns bei (append) die Lokalitäten nicht passen (hinten), dann müssen wir doch nur die Argumente vertauschen:
(append '("blau" "gelb")'("rot" "grün"))
    =>  ("blau" "gelb" "rot" "grün")

(append '("rot" "grün")'("blau" "gelb"))
    =>  ("rot" "grün" "blau" "gelb")
                  
Schwieriger wird es bei (cons). Wir können nicht einfach die Argumente vertauschen, da sonst statt der Liste, die wir uns vorstellen, ein chinesischer Nackthund entsehen könnte. Trotzdem - wir können auch mit (cons) ein Element hinten anhängen. Wir nehmen einfach den Umweg über (reverse). Diese Funktion dreht eine Liste einfach um - Liste rückwärts.
(reverse '("rot" "grün" "blau"))
  => ("blau "grün" "rot")
                  
Und wie soll das jetzt mit (cons) und (reverse) gehen? Wir wollten doch nur ein Element hinten anhängen! So geht das:
(reverse(cons "rot"(reverse '("gelb" "grün" "blau"))))
  =>  ("gelb" "grün" "blau" "rot")
                  
Wir hätten das - Sie haben das doch gewußt! - aber auch mit
(append '("gelb" "grün" "blau")'("rot"))
  =>  ("gelb" "grün" "blau" "rot")
                  
erreicht. Jedenfalls kennen wir jetzt auch (reverse). Wir sollten uns jetzt aber noch einer Gruppe von Funktionen zuwenden, die fast das Gegenteil von dem bewirkt, was wir bisher so gemacht haben. Bis jetzt haben wir uns damit befaßt, die Listen zu erstellen und immer mehr Elemente hinzuzufügen. Die Frage ist jetzt: Wie kommen wir an einzelne Elemente in Listen heran? Darum geht es im nächsten Kapitel.


Übungsaufgaben