Книга: Practical Common Lisp
Assignment
Assignment
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 place value)
Because SETF
is a macro, it can examine the form of the place it's assigning to and expand into appropriate lower-level operations to manipulate that place. When the place is a variable, it expands into a call to the special operator SETQ
, which, as a special operator, has access to both lexical and dynamic bindings.[81] For instance, to assign the value 10 to the variable x
, you can write this:
(setf x 10)
As I discussed earlier, assigning a new value to a binding has no effect on any other bindings of that variable. And it doesn't have any effect on the value that was stored in the binding prior to the assignment. Thus, the SETF
in this function:
(defun foo (x) (setf x 10))
will have no effect on any value outside of foo
. The binding that was created when foo
was called is set to 10, immediately replacing whatever value was passed as an argument. In particular, a form such as the following:
(let ((y 20))
(foo y)
(print y))
will print 20, not 10, as it's the value of y
that's passed to foo
where it's briefly the value of the variable x
before the SETF
gives x
a new value.
SETF
can also assign to multiple places in sequence. For instance, instead of the following:
(setf x 1)
(setf y 2)
you can write this:
(setf x 1 y 2)
returns the newly assigned value, so you can also nest calls to
SETFSETF
as in the following expression, which assigns both x
and y
the same random value:
(setf x (setf y (random 10)))