Other Ways to Modify Places
While all assignments can be expressed with **SETF**
, certain patterns involving assigning a new value based on the current value are sufficiently common to warrant their own operators. For instance, while you could increment a number with **SETF**
, like this:
(setf x (+ x 1))
or decrement it with this:
(setf x (- x 1))
it’s a bit tedious, compared to the C-style ++x
and --x
. Instead, you can use the macros **INCF**
and **DECF**
, which increment and decrement a place by a certain amount that defaults to 1.
(incf x) === (setf x (+ x 1))
(decf x) === (setf x (- x 1))
(incf x 10) === (setf x (+ x 10))
**INCF**
and **DECF**
are examples of a kind of macro called modify macros. Modify macros are macros built on top of **SETF**
that modify places by assigning a new value based on the current value of the place. The main benefit of modify macros is that they’re more concise than the same modification written out using **SETF**
. Additionally, modify macros are defined in a way that makes them safe to use with places where the place expression must be evaluated only once. A silly example is this expression, which increments the value of an arbitrary element of an array:
(incf (aref *array* (random (length *array*))))
A naive translation of that into a **SETF**
expression might look like this:
(setf (aref *array* (random (length *array*)))
(1+ (aref *array* (random (length *array*)))))
However, that doesn’t work because the two calls to **RANDOM**
won’t necessarily return the same value—this expression will likely grab the value of one element of the array, increment it, and then store it back as the new value of a different element. The **INCF**
expression, however, does the right thing because it knows how to take apart this expression:
(aref *array* (random (length *array*)))
to pull out the parts that could possibly have side effects to make sure they’re evaluated only once. In this case, it would probably expand into something more or less equivalent to this:
(let ((tmp (random (length *array*))))
(setf (aref *array* tmp) (1+ (aref *array* tmp))))
In general, modify macros are guaranteed to evaluate both their arguments and the subforms of the place form exactly once each, in left-to-right order.
The macro **PUSH**
, which you used in the mini-database to add elements to the *db*
variable, is another modify macro. You’ll take a closer look at how it and its counterparts **POP**
and **PUSHNEW**
work in Chapter 12 when I talk about how lists are represented in Lisp.
Finally, two slightly esoteric but useful modify macros are **ROTATEF**
and **SHIFTF**
. **ROTATEF**
rotates values between places. For instance, if you have two variables, a
and b
, this call:
(rotatef a b)
swaps the values of the two variables and returns **NIL**
. Since a
and b
are variables and you don’t have to worry about side effects, the previous **ROTATEF**
expression is equivalent to this:
(let ((tmp a)) (setf a b b tmp) nil)
With other kinds of places, the equivalent expression using **SETF**
would be quite a bit more complex.
**SHIFTF**
is similar except instead of rotating values it shifts them to the left—the last argument provides a value that’s moved to the second-to-last argument while the rest of the values are moved one to the left. The original value of the first argument is simply returned. Thus, the following:
(shiftf a b 10)
is equivalent—again, since you don’t have to worry about side effects—to this:
(let ((tmp a)) (setf a b b 10) tmp)
Both **ROTATEF**
and **SHIFTF**
can be used with any number of arguments and, like all modify macros, are guaranteed to evaluate them exactly once, in left to right order.
With the basics of Common Lisp’s functions and variables under your belt, now you’re ready to move onto the feature that continues to differentiate Lisp from other languages: macros.
1Dynamic variables are also sometimes called special variables for reasons you’ll see later in this chapter. It’s important to be aware of this synonym, as some folks (and Lisp implementations) use one term while others use the other.
2Early Lisps tended to use dynamic variables for local variables, at least when interpreted. Elisp, the Lisp dialect used in Emacs, is a bit of a throwback in this respect, continuing to support only dynamic variables. Other languages have recapitulated this transition from dynamic to lexical variables—Perl’s local
variables, for instance, are dynamic while its my
variables, introduced in Perl 5, are lexical. Python never had true dynamic variables but only introduced true lexical scoping in version 2.2. (Python’s lexical variables are still somewhat limited compared to Lisp’s because of the conflation of assignment and binding in the language’s syntax.)
3Actually, it’s not quite true to say that all type errors will always be detected—it’s possible to use optional declarations to tell the compiler that certain variables will always contain objects of a particular type and to turn off runtime type checking in certain regions of code. However, declarations of this sort are used to optimize code after it has been developed and debugged, not during normal development.
4As an optimization certain kinds of objects, such as integers below a certain size and characters, may be represented directly in memory where other objects would be represented by a pointer to the actual object. However, since integers and characters are immutable, it doesn’t matter that there may be multiple copies of “the same” object in different variables. This is the root of the difference between **EQ**
and **EQL**
discussed in Chapter 4.
5In compiler-writer terms Common Lisp functions are “pass-by-value.” However, the values that are passed are references to objects. This is similar to how Java and Python work.
6The variables in **LET**
forms and function parameters are created by exactly the same mechanism. In fact, in some Lisp dialects—though not Common Lisp—**LET**
is simply a macro that expands into a call to an anonymous function. That is, in those dialects, the following:
(let ((x 10)) (format t "~a" x))
is a macro form that expands into this:
((lambda (x) (format t "~a" x)) 10)
7Java disguises global variables as public static fields, C uses extern
variables, and Python’s module-level and Perl’s package-level variables can likewise be accessed from anywhere.
8If you specifically want to reset a **DEFVAR**
ed variable, you can either set it directly with **SETF**
or make it unbound using **MAKUNBOUND**
and then reevaluate the **DEFVAR**
form.
9The strategy of temporarily reassigning *standard-output* also breaks if the system is multithreaded—if there are multiple threads of control trying to print to different streams at the same time, they’ll all try to set the global variable to the stream they want to use, stomping all over each other. You could use a lock to control access to the global variable, but then you’re not really getting the benefit of multiple concurrent threads, since whatever thread is printing has to lock out all the other threads until it’s done even if they want to print to a different stream.
10The technical term for the interval during which references may be made to a binding is its extent. Thus, scope and extent are complementary notions—scope refers to space while extent refers to time. Lexical variables have lexical scope but indefinite extent, meaning they stick around for an indefinite interval, determined by how long they’re needed. Dynamic variables, by contrast, have indefinite scope since they can be referred to from anywhere but dynamic extent. To further confuse matters, the combination of indefinite scope and dynamic extent is frequently referred to by the misnomer dynamic scope.
11Though the standard doesn’t specify how to incorporate multithreading into Common Lisp, implementations that provide multithreading follow the practice established on the Lisp machines and create dynamic bindings on a per-thread basis. A reference to a global variable will find the binding most recently established in the current thread, or the global binding.
12This is why dynamic variables are also sometimes called special variables.
13If you must know, you can look up **DECLARE**
, **SPECIAL**
, and **LOCALLY**
in the HyperSpec.
14Several key constants defined by the language itself don’t follow this convention—not least of which are **T**
and **NIL**
. This is occasionally annoying when one wants to use t
as a local variable name. Another is **PI**
, which holds the best long-float approximation of the mathematical constant pi.
15Some old-school Lispers prefer to use **SETQ**
with variables, but modern style tends to use **SETF**
for all assignments.
16Look up **DEFSETF**
, **DEFINE-SETF-EXPANDER**
for more information.
17The prevalence of Algol-derived syntax for assignment with the “place” on the left side of the =
and the new value on the right side has spawned the terminology lvalue, short for “left value,” meaning something that can be assigned to, and rvalue, meaning something that provides a value. A compiler hacker would say, “**SETF**
treats its first argument as an lvalue.”
18C programmers may want to think of variables and other places as holding a pointer to the real object; assigning to a variable simply changes what object it points to while assigning to a part of a composite object is similar to indirecting through the pointer to the actual object. C++ programmers should note that the behavior of =
in C++ when dealing with objects—namely, a memberwise copy—is quite idiosyncratic.