Wenn wir die Funktion + bemühen, um die Zahlen 3 und 4 zu addieren, dann
wird sie uns als Ergebnis 7 zurückgeben. Abgesehen davon ändert sich
nichts: Die Funktion schreibt nichts auf die Festplatte, manipuliert keine
weiteren Daten im Speicher, ändert nicht das Aussehen des Bildschirms usw.
Wenn sie ausgeführt ist, ist alles wieder beim Alten. Wenn wir mit
(set ...)
oder
(setq ...) irgendeiner Variablen einen Wert zuweisen, liegt ein etwas
anderer Fall vor: Diese Bindung bleibt bestehen, auch wenn der set-Aufruf
längst beendet ist. Ebenso ist es, wenn wir mit
(defun ...) eine Funktion
definieren.
Bei der Rückgabe von + sprechen wir vom Effekt, die Auswirkungen von set, setq
und defun nennen wir Seiten- oder Nebeneffekt. Diese Dinge müssen wir sorgfältig
zu unterscheiden lernen. Eine Zuweisung mit setq hat also als Seiteneffekt, dass
der Variablen (oder auch mehreren) ein Wert zugewiesen wird, der Effekt ist immer
der Wert der letzten Zuweisung.
(setq my-var1 -13.05 my-var2 153.76)
=> 153.76 ; dies ist der Effekt
Man sollte die Begriffe nicht falsch bewerten: Sie haben nichts damit zu
tun, was wir im Alltag unter einem Neben- oder Haupteffekt verstehen, der
Seiten- bzw. Nebeneffekt einer Funktion kann durchaus der Hauptzweck sein.
Niemand wird Funktionen wie setq oder defun ihrer Rückgabe, also ihres
Effektes wegen verwenden!
Funktionen, die man wegen ihres Effekts aufruft, können in Verschachtelungen
eingebettet werden, solche, bei denen der Nebeneffekt im Vordergrund steht,
werden meist allein für sich stehend ausgeführt. Da aber jede Funktion einen
Effekt hat (aber nur wenige einen Nebeneffekt), kann es hier Ausnahmen geben.
Konstruktionen wie
(setq var-xx(defun func-yy ... )...) sind also nicht
per se ausgeschlossen, aber doch eher ungewöhnlich.
Andererseits haben viele AutoLisp-Programmierer ganz offensichtliche Hemmungen,
dort, wo es Sinn macht, Effekte zu verschachteln. Nehmen wir als Beispiel
eine Funktion, die die Farbe eines Kreises ändern soll. Zunächst das abschreckende
Beispiel:
(defun farbe(ent farbe / entdaten altefarbe neudaten)
(setq entdaten(entget ent))
(setq altefarbe (cdr(assoc 62 entdaten)))
(if(= altefarbe nil)
(setq neudaten
(append entdaten(list(cons 62 farbe)))
)
(setq neudaten
(subst altefarbe(cons 62 farbe)entdaten)
)
)
(entmod neudaten)
)
Auf manches hier kann aber wirklich verzichtet werden, wenn wir versuchen, den
Effekt einer Funktion als Eingabe für die nächste zu verwenden. Etwas gestrafft
würde die Funktion dann so aussehen:
(defun farbe(ent farbe / entdaten altefarbe)
(entmod
(if
(setq altefarbe
(assoc 62(setq entdaten(entget ent)))
)
(subst altefarbe (cons 62 farbe) entdaten)
(append entdaten(list(cons 62 farbe)))
)
)
)
Es spricht überhaupt nichts dagegen, die if-Anweisung in den entmod-Aufruf
einzubetten. Ebenso funktionieren die setq-Anweisungen auch dann, wenn sie
nicht allein auf einer Zeile stehen! Das Verketten von Effekten spart Rechenzeit,
das Zwischenspeichern mit
setq verbraucht dagegen recht viel. Lisp kannte
übrigens am Anfang gar keine Variablenbindung, diese wurden erst später
hinzugefügt.