Es gibt mehrere Möglichkeiten, Variablen einzuführen.
DEFVAR und DEFPARAMETER einführen globale dynamische Variablen. DEFVAR
legt optional einen Wert fest, sofern es nicht bereits definiert ist. DEFPARAMETER
setzt es immer auf den angegebenen Wert. SETQ keine Variable einzuführen.
(defparameter *number-of-processes* 10)
(defvar *world* (make-world)) ; the world is made only once.
Beachten Sie, dass Sie wahrscheinlich nie wie DEFVAR
Variablen mit Namen wollen x
, y
, stream
, limit
, ... Warum? Weil diese Variablen dann als speziell deklariert werden und es schwierig ist, das rückgängig zu machen. Die spezielle Deklaration ist global und alle weiteren Verwendungen der Variablen würden eine dynamische Bindung verwenden.
BAD:
(defvar x 10) ; global special variable X, naming convention violated
(defvar y 20) ; global special variable Y, naming convention violated
(defun foo()
(+ x y)) ; refers to special variables X and y
(defun bar (x y) ; OOPS!! X and Y are special variables
; even though they are parameters of a function!
(+ (foo) x y))
(bar 5 7) ; -> 24
Besser: Immer spezielle Variablen mit *
in ihrem Namen markieren!
(defvar *x* 10) ; global special variable *X*
(defvar *y* 20) ; global special variable *Y*
(defun foo()
(+ *x* *y*)) ; refers to special variables X and y
(defun bar (x y) ; Yep! X and Y are lexical variables
(+ (foo) x y))
(bar 5 7) ; -> 42
Lokale Variablen werden eingeführt mit DEFUN, LAMBDA, LET, MULTIPLE-VALUE-BIND und viele andere.
(defun foo (i-am-a-local-variable)
(print i-am-a-local-variable))
(let ((i-am-also-a-local-variable 'hehe))
(print i-am-also-a-local-variable))
nun standardmäßig die lokalen Variablen in beiden oben genannten Formen sind lexikalische, es sei denn, sie SPECIAL deklariert sind. Dann wären sie dynamische Variablen.
Als nächstes gibt es auch mehrere Formen eine Variable, um neue Werte zu setzen.SET, SETQ, SETF und andere. SETQ
und SETF
können sowohl lexikalische und spezielle (dynamisch) Variablen gesetzt.
Es ist für den portablen Code erforderlich, die eine Variable setzt, die bereits deklariert sind. Der genaue Effekt des Festlegens einer nicht deklarierten Variablen ist vom Standard nicht definiert.
Also, wenn Sie wissen, was Ihre Common Lisp Implementierung der Fall ist, können Sie
(setq world (make-new-world))
im Read-Eval-Print-Loop- im Toplevel verwenden. Aber benutze es nicht in deinem Code, da der Effekt nicht tragbar ist. Normalerweise wird SETQ
die Variable festlegen. Aber einige Implementierung könnte auch erklären, die Variable SPECIAL wenn sie es nicht weiß (CMU Common Lisp tut das Standard). Das ist fast immer nicht das, was man möchte. Verwenden Sie es für den gelegentlichen Gebrauch, wenn Sie wissen, was Sie tun, aber nicht für Code.
Hier gilt das gleiche:
(defun make-shiny-new-world()
(setq world (make-world 'shiny)))
Zunächst sollten Variablen wie *world*
geschrieben werden (mit den umliegenden *
Zeichen), um deutlich zu machen, dass es eine globale spezielle Variable ist. Zweitens sollte es zuvor mit DEFVAR
oder DEFPARAMETER
deklariert worden sein.
Ein typischer Lisp-Compiler wird sich beschweren, dass die obige Variable nicht deklariert ist. Da in Common Lisp keine globalen lexikalischen Variablen vorhanden sind, muss der Compiler Code für eine dynamische Suche generieren. Einige Compiler sagen dann, okay, wir nehmen an, dass dies ein dynamischer Lookup ist, lassen Sie uns es als special deklarieren - da das ist, was wir ohnehin annehmen.
Ich bin überrascht, dass, wenn Sie die Variable global mit Defvar deklariert haben, es keine Möglichkeit gibt, eine lokale Variable mit dem gleichen Namen zu machen, so (x() x) kann zu unerwarteten Ergebnissen führen, wenn x wird von defvar deklariert. – Ian
@ian Das ist ein Grund, warum viele Leute "Ohrenschützer" benutzen (das heißt, sie benutzen nie '(defvar x foo)', sie benutzen '(defvar * x * foo)', auf diese Weise ist es viel weniger wahrscheinlich einen Fehler machen. – Vatine