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










Eine der Aufgaben aus dem letzten Kapitel lautete, einen Weg zu finden, der sicherstellt, dass bei einer Division zweier Variablen ein Ergebnis mit Kommastellen herauskommt, und zwar unabhängig davon, ob die Variablen Realzahlen oder Ganzzahlen enthalten. Die Lösung könnte z.B. so aussehen: (/(* 1.0 zahl1)zahl2). Damit wäre eines der Argumente auf jeden Fall eine Realzahl, und die Korrektheit des Ergebnisses wäre sichergestellt. AutoLISP bietet jedoch in Gestalt der Funktion (float) eine einfachere Lösung:
(/(float zahl1)zahl2)
;oder auch
(/ zahl1(float zahl2))
(float) wandelt eine Integerzahl in eine Realzahl um (wenn das Argument schon eine Realzahl ist, passiert gar nichts). Bedenken Sie aber, dass der Inhalt der Variablen hier in keiner Weise geändert wird, nur die Rückgabe der Evaluation wird modifiziert! Den Variablenwert selbst müssen Sie mit (setq) ändern.

Noch ein Beispiel, um das zu verdeutlichen:
(setq vari_1 7)          =>   7

(setq vari_2 2)          =>   2

(/ vari_1 vari_2)        =>   3
;Ganzzahldivision!

(float vari_1)           =>   7.0
;Gibt zwar den geänderten Rückgabewert zurück,
;ändert aber nicht den Wert der Variablen vari_1!

(/ vari_1 vari_2)        =>   3
;immer noch Ganzzahldivision!

(/(float vari_1)vari_2)  =>   3.5
;Realzahldivision, die Variablen haben aber
;immer noch den alten Wert

(setq vari_1(float vari_1)
;Erst jetzt ändert sich der Wert der Variablen
Auch (setq) kann in verschachtelten Ausdrücken vorkommen:
(setq z3(+(setq z1 -3)(setq z2(1- z1))))
Hier bekommt z3 den Wert -7 zugewiesen. Überlegen Sie nun, warum die folgende Eingabe (wahrscheinlich) nicht korrekt ist:
(setq radius1
  (*
    (setq radius3(/(float radius2)2))
    (setq radius2 25)
  )
)
Ist der Groschen bei Ihnen gefallen? Es wird der Variablen radius3 der halbe Wert von radius2 zugewiesen, bevor radius2 überhaupt einen Wert hat. Es entsteht also ein Problem der Reihenfolge der Abarbeitung. Die Einschränkung, dass die Eingabe 'wahrscheinlich' nicht korrekt ist, hat folgenden Grund: Es könnte ja sein, dass radius2 vorher schon irgendwoher einen alten Wert hatte, der jetzt überschrieben wird. Mit anderen Worten: Wenn Sie jetzt diese Zeile eintippen, werden Sie sich mit Sicherheit die gelbe Karte einhandeln. Sieht man die Zeile als Bruchstück eines Programms, könnte Sie durchaus korrekt sein.

Es gibt übrigens eine Gegenteilsfunktion zu (float), die (fix) heisst und die (nein, es wird nichts schneller) Real- in Integerzahlen umwandelt. Das bedeutet aber, dass der nichtganzzahlige Anteil verlorengeht. Ausprobieren!

Und nun zu einem Thema, das Ihnen am Anfang vielleicht etwas Schwierig- keiten verursachen wird: Wenn LISP einen Ausdruck evaluiert, wird in der Regel jedes Element des Ausdrucks (von links nach rechts) evaluiert. Wenn Sie also den Ausdruck (+ var1 var2) eingeben, passiert folgendes:
  • Der Funktionsname + wird evaluiert. Dies bedeutet, dass statt des Namens der Funktion die Funktion selbst eingesetzt wird
  • Das Symbol var1 wird evaluiert, nehmen wir an, der Wert sei 6.
  • Das Symbol var2 wird evaluiert, nehmen wir an, der Wert sei 4.
  • Jetzt kann der Funktionsablauf (in diesem Fall der Additionsprozess), der an den Namen + gebunden ist, mit den Argumenten 6 und 4 durchgeführt werden.
Untersuchen wir nun eine Zuweisung wie z.B.: (setq durchmesser 3.5). Analog zum vorigen Beipiel müsste also folgendes passieren:
  • Der Funktionsname setq wird evaluiert und die Funktion selbst eingesetzt.
  • Das Symbol durchm wird evaluiert und durch seinen Wert ersetzt.
    ???
    Halt! Das kann ja wohl nicht sein! Wir wollen dem Symbol durchmesserdoch erst einen Wert zuweisen!
Es ist tatsächlich so, dass Argumente einer Funktion nicht ausnahmslos evaluiert werden. Wann Argumente evaluiert werden und wann nicht, hängt von der aufgerufenen Funktion ab. Bei (setq ...) ist es so, dass das erste Argument nicht evaluiert wird, jedoch das zweite. Bei den Rechenfunktionen werden grundsätzlich alle Argumente evaluiert. Übrigens: wenn Zahlen evaluiert werden, ist der Wert der Zahl immer die Zahl selbst.

Also nochmal: Der Evaluations-Ablauf von (setq durchmesser 3.5)
  • Der Funktionsname setq wird evaluiert und die Funktion selbst eingesetzt.
  • Das Symbol durchmesser wird nicht evaluiert, sondern bleibt als Name stehen
  • Die Zahl 3.5 wird zwar evaluiert. Die Evaluation von Zahlen ergibt aber immer die Zahl selbst, also ändert sich auch hier nichts.
  • Jetzt kann der an den Namen setq gebundene Ablauf mit den Argumenten durchmesser und 3.5 durchgeführt werden, d.h. die Zahl 3.5 wird an das Symbol durchmesser gebunden.
Es gibt ausser setq noch weitere Funktionen, die verhindern, dass ihre Argumente ganz oder teilweise evaluiert werden. Doch dazu später. Nun zu einer weiteren Funktion namens (set), die fast das selbe tut wie (setq), aber mit dem kleinen Unterschied, dass sie die Evaluation ihres ersten Arguments nicht verhindert. Und dann gibt es noch die Funktion (quote). Diese bekommt ein Argument und verhindert, dass das Argument evaluiert wird. Sie kann jederzeit und überall dazu eingesetzt werden, um eine Evaluation zu verhindern.

Auch wenn jetzt vielleicht ein deutliches Stöhnen zu vernehmen ist, sehen Sie sich doch bitte einmal dieses Beispiel an:
(set(quote durchm)3.5)
Was passiert hier? Erstens: Wie gehabt wird der Funktionsname set durch die Funktionsprozedur selbst ersetzt. Zweitens: Im Gegensatz zu (setq) verhindert (set) nicht die Evaluation des ersten Arguments. Durch den Einsatz von (quote) wird sie nun aber doch verhindert. Drittens: Die Zahl 3.5 wird zu 3.5 evaluiert, weil Zahlen immer sich selbst ergeben, wenn sie evaluiert werden. Wir können also schliessen, dass die beiden Ausdrücke (setq durchm 3.5) und (set(quote durchm)3.5) ein völlig identisches Verhalten an den Tag legen. Das heisst aber nicht, dass sie identisch sind - sie sind äquivalent.

Was können wir nun mit (set) und (quote) anfangen? Versuchen Sie, das nächste Beispiel nachzuvollziehen:
(setq var1(quote var2))
(set var1 99)
Ganz kurz gefasst: Wir weisen der Variablen var1 den Wert var2 zu. Anschliessend weisen wir dem Wert von var1 den Wert 99 zu. Es hat jetzt also, da var1 den Wert var2 hat, die Variable var2 den Wert 99.

Die Welt ist voller Was-wäre-wenn, also lassen Sie uns noch ein paar solcher Überlegungen anstellen. Was wäre also, wenn wir zuerst (set var1(quote var2)) geschrieben hätten? Antwort: var1 wäre evaluiert worden. Da es noch keinen Wert hatte, hätte die Sache nicht funktioniert. Was wäre gewesen, wenn wir var2 nicht gequotet hätten? Wir hätten damit var1 den Wert 'keinen Wert' zugewiesen. Keinen Wert hatte aber var1 sowieso schon. Und was wäre gewesen, wenn wir (setq var1 99) als zweite Anweisung eingegeben hätten? Dann hätten wir nicht var2, sondern var1 den Wert 99 zugewiesen.

Noch einige Dinge, die nicht unerwähnt bleiben dürfen: (setq ...) ist einfach eine Abkürzung für 'set quoted'. Für die Funktion (quote) gibt es eine andere Schreibweise: Man setzt einfach ein Hochkomma vor den betreffenden Ausdruck. Das letzte Beispiel sieht dann so aus:
(setq var1 'var2)   => var2
(set var1 99)       => 99
Der Wert "Kein-Wert" heisst in LISP nil. Die Evaluation eines Ausdrucks ohne Wert ergibt immer nil. Wenn wir also annehmen, dass den Variablen var1 und var2 bisher kein Wert zugeordnet wurde, ergibt sich dieses Bild:
(setq var1 var2)    => nil
;Der Variablen var1 wird der Wert nil zugewiesen,
;da var2 keinen Wert hat und die Evaluation von
;var2 nil ergibt. Es ändert sich also gar nichts,
;da var1 auch vor dieser Operation den Wert nil
;hatte.

(setq var1 77)      => 77
;Jetzt hat var1 den Wert 77

(setq var1 nil)     => nil
;Alles wieder wie vorher - kein Wert.
Die Funktion (setq) kann auch mehr als zwei Argumente haben. Sie können eingeben: (setq a 1 b 2 c 3) und erzielen damit das selbe Ergebnis wie durch Eingabe von (setq a 1)(setq b 2)(setq c 3). Die Argumente müssen aber immer paarweise vorhanden sein. Selbstverständlich wird die Evaluation jedes ersten Argumentes eines Paares verhindert.

Und hier mal wieder das Wichtigste aus den beiden letzten Kapiteln in Kürze zusammengefasst:
  • Zuweisungen von Werten an Namen (Symbole) führt man mit der Funktion (setq) durch.
  • Man sollte darauf achten, daá man durch die Wahl von Symbolnamen keine bestehenden AutoLISP-Funktionen entdefiniert.
  • Variablennamen sollten deskriptiv sein, d.h. man sollte auch am übernächsten Tag noch erkennen können, was man sich dabei gedacht hat.
  • Wenn ein Ausdruck evaluiert wird, wird (von links nach rechts) jedes seiner Elemente evaluiert, es sei denn, die Evaluation wird verhindert.
  • Zahlen werden durch Evaluation nicht verändert.
  • Es gibt Funktionen, die die Evaluation eines oder mehrerer ihrer Argumente verhindern.
  • Die Funktion (setq) verhindert die Evaluation ihres ersten Argumentes.
  • Die Funktion (set) verhindert keine Evaluation ihrer Argumente.
  • Die Funktion (quote) dient dazu, die Evaluation eines beliebigen Ausdrucks zu verhindern.
  • 'Kein-Wert' heisst in AutoLISP nil. Das Zuweisen von nil mit (setq) bedeutet das Entfernen eines evtl. zugewiesenen Wertes.

Übungsaufgaben

  1. Sie haben folgendes eingegeben:
    (setq var1 27) => 27
    (float var1) => 27.0
    Wenn Sie nun folgendes eingeben: (setq var2 var1), welchen Wert hat dann die Variable var2?

  2. Sie haben folgendes eingegeben:
    (setq var1 49)
    (setq var2(*(sqrt var1)(sqrt var1)))
    Hat var2 jetzt den selben Wert wie var1?

  3. Sie haben folgendes eingegeben:
    (setq var1 103 var2 -37 var3(+ var1 var2) var1 0) Welchen Wert hat jetzt var3?

  4. Sie haben folgendes eingegeben:
    (setq var3(+(setq var1 103)(setq var2 -37))var1 0)
    Ist jetzt alles genauso wie in der vorigen Aufgabe, und ist dies überhaupt eine korrekte Eingabe?

  5. Kann man auch (set) genauso wie (setq) mit beliebig vielen Paaren von Argumenten aufrufen?

  6. Wieviele Argumente kann man der Funktion (quote) mitgeben?

  7. Zählen Sie alle Funktionen auf, die bisher bekannt sind, mit denen man den Wert einer Variablen verändern kann.

  8. Welche Aussagen sind richtig:
    • Die Funktion (quote) sorgt dafür, dass ein Funktionsargument evaluiert wird, auch wenn die Funktion die Evaluation eigentlich verhindert.

    • Der Ausdruck (quote x) kann auch (' x) geschrieben werden.

    • Die Ausdrücke (set(quote y)3) und (setq y 3) sind völlig identisch.

    • Die Ausdrücke (setq(quote y)3) und (set y 3) sind in der Wirkung gleich

    • Den Wert nil kann man gar nicht zuweisen.

    • Symbole, die keinen Wert haben, gibt es nicht.

  9. Welche der folgenden Eingaben erzeugt einen Fehler?
    (setq nil 3)
    (setq 3 nil)
    (set 'a 'b)
    (setq a 1 b 2 c 3)
    (set 'a 1 'b 2 'c 3)
    (setq var1(float 1.5))
    (setq var1(fix pi))

  10. Sie sind nur am Nachkommaanteil des Wertes der Variablen real_var interessiert. Wie berechnen Sie ihn?

  11. Ist es richtig, dass die Funktion (setq) in AutoLISP gar nicht unbedingt notwendig ist, d.h. wäre AutoLISP irgendwie eingeschränkt, wenn es (setq) nicht gäbe?

  12. Welchen Wert hat die Variable a zum Schluss, wenn Sie folgendes nacheinander eingeben:
    (setq a 'b)
    (setq b 'c)
    (set a 1)
    (set b 2)