(foo))
Note that the middle call to foo
is wrapped in a LET
that binds *x*
to the new value 20. When you run bar
, you get this result:
CL-USER> (bar)
X: 10
X: 20
X: 10
NIL
As you can see, the first call to foo
sees the global binding, with its value of 10. The middle call, however, sees the new binding, with the value 20. But after the LET
, foo
once again sees the global binding.
As with lexical bindings, assigning a new value affects only the current binding. To see this, you can redefine foo
to include an assignment to *x*
.
(defun foo ()
(format t 'Before assignment~18tX: ~d~%' *x*)
(setf *x* (+ 1 *x*))
(format t 'After assignment~18tX: ~d~%' *x*))
Now foo
prints the value of *x*
, increments it, and prints it again. If you just run foo
, you'll see this:
CL-USER> (foo)
Before assignment X: 10
After assignment X: 11
NIL
Not too surprising. Now run bar
.
CL-USER> (bar)
Before assignment X: 11
After assignment X: 12
Before assignment X: 20
After assignment X: 21
Before assignment X: 12
After assignment X: 13
NIL
Notice that *x*
started at 11—the earlier call to foo
really did change the global value. The first call to foo
from bar
increments the global binding to 12. The middle call doesn't see the global binding because of the LET
. Then the last call can see the global binding again and increments it from 12 to 13.
So how does this work? How does LET
know that when it binds *x*
it's supposed to create a dynamic binding rather than a normal lexical binding? It knows because the name has been declared DEFVAR
and DEFPARAMETER
is automatically declared globally special. This means whenever you use such a name in a binding form—in a LET
or as a function parameter or any other construct that creates a new variable binding—the binding that's created will be a dynamic binding. This is why the *naming* *convention*
is so important—it'd be bad news if you used a name for what you thought was a lexical variable and that variable happened to be globally special. On the one hand, code you call could change the value of the binding out from under you; on the other, you might be shadowing a binding established by code higher up on the stack. If you always name global variables according to the *
naming convention, you'll never accidentally use a dynamic binding where you intend to establish a lexical binding.
It's also possible to declare a name locally special. If, in a binding form, you declare a name special, then the binding created for that variable will be dynamic rather than lexical. Other code can locally declare a name special in order to refer to the dynamic binding. However, locally special variables are relatively rare, so you needn't worry about them.[79]
Dynamic bindings make global variables much more manageable, but it's important to notice they still allow action at a distance. Binding a global variable has two at a distance effects—it can change the behavior of downstream code, and it also opens the possibility that downstream code will assign a new value to a binding established higher up on the stack. You should use dynamic variables only when you need to take advantage of one or both of these characteristics.
One other kind of variable I haven't mentioned at all is the oxymoronic 'constant variable.' All constants are global and are defined with DEFCONSTANT
. The basic form of DEFCONSTANT
is like DEFPARAMETER
.
(defconstant
As with DEFVAR
and DEFPARAMETER
, DEFCONSTANT
has a global effect on the name used—thereafter the name can be used only to refer to the constant; it can't be used as a function parameter or rebound with any other binding form. Thus, many Lisp programmers follow a naming convention of using names starting and ending with +
for constants. This convention is somewhat less universally followed than the *
-naming convention for globally special names but is a good idea for the same reason.[80]
Another thing to note about DEFCONSTANT
is that while the language allows you to redefine a constant by reevaluating a DEFCONSTANT
with a different initial-value-form, what exactly happens after the redefinition isn't defined. In practice, most implementations will require you to reevaluate any code that refers to the constant in order to see the new value since the old value may well have been inlined. Consequently, it's a good idea to use DEFCONSTANT
only to define things that are DEFPARAMETER
instead.
Once you've created a binding, you can do two things with it: get the current value and set it to a new value. As you saw in Chapter 4, a symbol evaluates to the value of the variable it names, so you can get the current value simply by referring to the variable. To assign a new value to a binding, you use the SETF
macro, Common Lisp's general-purpose assignment operator. The basic form of SETF
is as follows:
(setf
Because SETF
is a macro, it can examine the form of the SETQ
, which, as a special operator, has access to both lexical and dynamic