Schauen wir uns eine typische Abfrage mal an.

(initget "Ja Nein")
(setq Abfrage (getkword "Soll ich wirklich alles löschen? [Ja/Nein] :"))
(if (and
     (not Abfrage)
     (= Abfrage "Nein")
     )
   'machwas-bei-nein
   'sonst-tue-was-da-ja
 )

Bei diesem Codeschnipsel zeigt sich Folgendes. Es wird eine Variable mit einer Benutzereingabe verknüpft. Dabei gibt es zwei Möglichkeiten, entweder wird die Variable gefüttert mit "Ja" oder "Nein" oder sie bleibt "leer" also nil. Dies passiert wenn der Benutzer die Enter Taste drückt. Nun wollen wir aber aus bestimmten Gründen, dass wenn der Benutzer die Enter-Taste drückt automatisch "Nein" der Variablen zugwiesen wird.

(initget "Ja Nein")
(setq Abfrage (getkword "Soll ich wirklich alles löschen? [Ja/Nein] <Nein>:"))
(if (not Abfrage) (setq Abfrage "Nein"))
...

Mit der Funktion initget bestimmen wir welche Antwortmöglichkeiten zur Verfügung stehen soll. Damit diese im Kontextmenü der Maus (Rechtsklick) erscheint, schreiben wir diese Antwortmöglichkeiten in eckigen Klammern ([...]). Als Trenner verwenden wir hierfür den Schrägstrich (Slash). Das Wort innerhalb der spitzen (<...>) Klammer soll dem Benutzer signalisieren, dass er durch Drücken der Enter-Taste diese Vorwahl trifft.

Über die Bedingungsfunktion cond kann man die Benutzereingaben eleganter programmieren.

(initget "Ja Nein")
(setq Abfrage (cond ((getkword "Soll ich wirklich alles löschen? [Ja/Nein] <Nein>:"))
   ("Nein")
   )
)

Die Funktion cond akzeptiert eine beliebige Zahl von Listen als Argumente. Das erste Element jeder Liste wird (in der gegebenen Reihenfolge) bearbeitet, bis eines dieser Elemente einen anderen Wert als nil zurückgibt.
Bei dem obenstehenden Code wird also innerhalb cond als erstes (getkword ...) evaluiert. Ist die Rückgabe der Abfrage ungleich nil, wird dessen Wert zurückgegeben, also in unserem Beispiel entweder "Ja" oder "Nein". Falls die Rückgabe jedoch nil ist (drücken der Enter-Taste), gilt die erste Liste als nicht erfüllt und somit wird die zweite Liste evaluiert. In unserem Beispiel ist sie auf jeden Fall True, denn die Rückgabe ist "Nein".

Ein anderes Beispiel.
Nehmen wir mal an, wir schreiben ein Programm bei dem drei Bedingungen vorh. sein sollen. 2 Abfragen bestehen aus Punkteingaben und eine Prüfroutine, ob ein Block vorhanden ist. Auch hier kann man sehr gut cond einsetzen.

(cond ;; Wenn MeinBlock vorh. ist, soll nil ausgeführt werden, damit innerhalb cond
;; weitergesprungen wird.
;; Sollte der Block nicht gefunden werden, dann gilt die doppelte "Verneinung" als wahr
;; In diesem Fall endet das Programm mit einer Meldung!
   ((not (or (tblsearch "BLOCK" "MeinBlock") (findfile "MeinBlock.dwg")))
   (prompt "Block \"MeinBlock\" nicht gefunden.\MeinBlock.dwg muss sich in einem Supportpfad befinden")
   )
;; Nachdem obere Bedingung erfüllt ist, also zu nil evaluiert wird, folgt hier die Eingabe eines Punktes
;; Sollte hier keiner eingegeben/geklickt werden, gibt die Funktion getpoint nil zurück
;; und das Programm endet hier.
   ((not (setq startpoint (getpoint "Startpunkt picken... :"))))
;; Analog wie oben
   ((not (setq endpoint (getpoint startpoint "Endpunkt picken... :"))))
;; Okay, alle erforderlichen Eingaben sind nun vorh. und es kann im Programm weiter gehen
   ('t 'machwas)
)

 Und das alles ohne if.

Noch ein Beispiel. Wir benötigen in unserem Programm einen Farbwert (ohne auf TrueColor-Werte einzugehen). Diese Abfrage sollte so ablaufen, dass als erstes eine Eingabeaufforderung stattfindet um direkt einen Integer-Farbwert anzugeben. Sollte der Benutzer jedoch die Enter-Taste drücken, soll durch klicken eines Objektes, dessen Farbe ausgelesen werden.

Und so könnte der Code aussehen...

(cond ((getint "Eingabe eines Farbwertes (Return= Objektfarbe picken) : "))
   ((null (while (not (setq pick (car (entsel)))) (princ "\nNix gepickt, nochmal bitte...")))
     (cond ((cdr (assoc 62 (entget pick))))
     ((cdr (assoc 62 (tblsearch "LAYER" (cdr (assoc 8 (entget pick)))))))
     )
   )
 )

Was passiert hier nun im Einzelnen?

Das 1. Listenelement des conds (getint) erwartet als Input einen Integerwert. Drückt der Anwender nun die Enter-Taste, wird das erste Listenelement der Bedingungsfunktion cond zu nil evaluiert und somit kommen wir zum 2.Listenelement.
 Hier haben wir gleich noch ein weiteres "Goodie" eingebaut. Wir führen innerhalb des ersten Listenelements eine while-Schleife aus. Sollte der Anwender kein Objekt geklickt haben, wird ein Text ausgegeben und die while-Schleife läuft weiter. Erst wenn der Anwender auf ein Objekt klickt, wird die while-Schleife mit einem nil(!) verlassen. Durch das vorangestellte null wird somit das Listenelement als true evaluiert. Jetzt befinden wir uns innerhalb der 2. Liste und hier haben wir ebenfalls wieder ein cond. Dieses cond versucht als erstes die Farbe des Objektes auszulesen. Sollte die Farbe jedoch VonLayer sein, gibt das erste Listenelement ein nil zurück (das Objekt hat in diesem Fall keinen Schlüssel für die Farbe) und springt zur nächsten Liste. Dort wird nun der Farbwert direkt aus dem Layer auf dem unser Objekt liegt entnommen. Wir erhalten auf jeden Fall als Rückgabe einen Integerwert.

 Sie fragen sich jetzt, warum hier keine if Abfrage eingebaut ist?
Nun, probieren wir es doch einmal...

(if (cdr (assoc 62 (entget pick)))
   (cdr (assoc 62 (entget pick)))
   (cdr (assoc 62 (tblsearch "LAYER" (cdr (assoc 8 (entget pick))))))
)

Der Ausdruck nach if wird entweder zu true oder zu nil evaluiert. Sollte also der Ausdruck true ergeben, müssen wir nun den Wert nochmal ausgeben (true nutzt uns also nix). Optimieren wir oben stehenden Code noch ein wenig und bauen ein setq ein.

(if (setq Color (cdr (assoc 62 (entget pick))))
   Color
   cdr (assoc 62 (tblsearch "LAYER" (cdr (assoc 8 (entget pick))))))
)

 Sieht zwar schon besser aus, aber die Version mit cond benötigt kein setq ! :-)

 

Mit freundlicher Genehmigung von Rolf Wischnewski. Originalbeitrag im Februar 2006, CADmaro.de

span style=null

Diese Internetseite ist urheberrechtlich geschützt. Alle Rechte vorbehalten.     © 2024 Markus Hoffmann (─┼──) www.CADmaro.de