Next: Customizing Setf, Previous: Basic Setf, Up: Generalized Variables [Contents][Index]
This package defines a number of other macros besides setf
that operate on generalized variables. Many are interesting and
useful even when the place is just a variable name.
This macro is to setf
what psetq
is to setq
:
When several places and forms are involved, the
assignments take place in parallel rather than sequentially.
Specifically, all subforms are evaluated from left to right, then
all the assignments are done (in an undefined order).
This macro increments the number stored in place by one, or
by x if specified. The incremented value is returned. For
example, (incf i)
is equivalent to (setq i (1+ i))
, and
(incf (car x) 2)
is equivalent to (setcar x (+ (car x) 2))
.
Once again, care is taken to preserve the “apparent” order of evaluation. For example,
(incf (aref vec (incf i)))
appears to increment i
once, then increment the element of
vec
addressed by i
; this is indeed exactly what it
does, which means the above form is not equivalent to the
“obvious” expansion,
(setf (aref vec (incf i)) (1+ (aref vec (incf i)))) ; Wrong!
but rather to something more like
(let ((temp (incf i))) (setf (aref vec temp) (1+ (aref vec temp))))
Again, all of this is taken care of automatically by incf
and
the other generalized-variable macros.
As a more Emacs-specific example of incf
, the expression
(incf (point) n)
is essentially equivalent to
(forward-char n)
.
This macro decrements the number stored in place by one, or by x if specified.
This macro removes and returns the first element of the list stored
in place. It is analogous to (prog1 (car place)
(setf place (cdr place)))
, except that it takes care
to evaluate all subforms only once.
This macro inserts x at the front of the list stored in
place. It is analogous to (setf place (cons
x place))
, except for evaluation of the subforms.
This macro inserts x at the front of the list stored in
place, but only if x was not eql
to any
existing element of the list. The optional keyword arguments
are interpreted in the same way as for adjoin
.
See Lists as Sets.
This macro shifts the places left by one, shifting in the
value of newvalue (which may be any Lisp expression, not just
a generalized variable), and returning the value shifted out of
the first place. Thus, (shiftf a b c
d)
is equivalent to
(prog1 a (psetf a b b c c d))
except that the subforms of a, b, and c are actually evaluated only once each and in the apparent order.
This macro rotates the places left by one in circular fashion.
Thus, (rotatef a b c d)
is equivalent to
(psetf a b b c c d d a)
except for the evaluation of subforms. rotatef
always
returns nil
. Note that (rotatef a b)
conveniently exchanges a and b.
The following macros were invented for this package; they have no analogues in Common Lisp.
This macro is analogous to let
, but for generalized variables
rather than just symbols. Each binding should be of the form
(place value)
; the original contents of the
places are saved, the values are stored in them, and
then the body forms are executed. Afterwards, the places
are set back to their original saved contents. This cleanup happens
even if the forms exit irregularly due to a throw
or an
error.
For example,
(letf (((point) (point-min)) (a 17)) ...)
moves “point” in the current buffer to the beginning of the buffer,
and also binds a
to 17 (as if by a normal let
, since
a
is just a regular variable). After the body exits, a
is set back to its original value and point is moved back to its
original position.
Note that letf
on (point)
is not quite like a
save-excursion
, as the latter effectively saves a marker
which tracks insertions and deletions in the buffer. Actually,
a letf
of (point-marker)
is much closer to this
behavior. (point
and point-marker
are equivalent
as setf
places; each will accept either an integer or a
marker as the stored value.)
Since generalized variables look like lists, let
’s shorthand
of using ‘foo’ for ‘(foo nil)’ as a binding would
be ambiguous in letf
and is not allowed.
However, a binding specifier may be a one-element list
‘(place)’, which is similar to ‘(place
place)’. In other words, the place is not disturbed
on entry to the body, and the only effect of the letf
is
to restore the original value of place afterwards. (The
redundant access-and-store suggested by the (place
place)
example does not actually occur.)
In most cases, the place must have a well-defined value on
entry to the letf
form. The only exceptions are plain
variables and calls to symbol-value
and symbol-function
.
If the symbol is not bound on entry, it is simply made unbound by
makunbound
or fmakunbound
on exit.
This macro is to letf
what let*
is to let
:
It does the bindings in sequential rather than parallel order.
This is the “generic” modify macro. It calls function,
which should be an unquoted function name, macro name, or lambda.
It passes place and args as arguments, and assigns the
result back to place. For example, (incf place
n)
is the same as (callf + place n)
.
Some more examples:
(callf abs my-number) (callf concat (buffer-name) "<" (int-to-string n) ">") (callf union happy-people (list joe bob) :test 'same-person)
See Customizing Setf, for define-modify-macro
, a way
to create even more concise notations for modify macros. Note
again that callf
is an extension to standard Common Lisp.
This macro is like callf
, except that place is
the second argument of function rather than the
first. For example, (push x place)
is
equivalent to (callf2 cons x place)
.
The callf
and callf2
macros serve as building
blocks for other macros like incf
, pushnew
, and
define-modify-macro
. The letf
and letf*
macros are used in the processing of symbol macros;
see Macro Bindings.
Next: Customizing Setf, Previous: Basic Setf, Up: Generalized Variables [Contents][Index]