A generalized reference is the use of a form,
sometimes called a place,
as if it were a variable that could be read and written.
The value of a place is
the object to which the place form evaluates.
The value of a place can be changed by using setf
.
The concept of binding a place is not defined in Common Lisp,
but an implementation is permitted to extend the language by defining this concept.
The next figure contains examples of the use of setf
.
Note that the values returned by evaluating the forms in column two
are not necessarily the same as those obtained by evaluating the
forms in column three.
In general, the exact macro expansion of a setf
form is not guaranteed
and can even be implementation-dependent;
all that is guaranteed is
that the expansion is an update form that works
for that particular implementation,
that the left-to-right evaluation of subforms is preserved,
and
that the ultimate result of evaluating setf
is the value
or values being stored.
|
Figure 5.1: Examples of setf
The next figure shows operators relating to places and generalized reference.
|
Figure 5.2: Operators relating to places and generalized reference.
Some of the operators above manipulate places
and some manipulate setf expanders.
A setf expansion can be derived from any place.
New setf expanders can be defined by using defsetf
and define-setf-expander
.
The following rules apply to the evaluation of subforms in a place:
get-setf-expansion
.
For all places defined by this specification
(e.g., getf
, ldb
, ...),
this order of evaluation is left-to-right.
When a place is derived from a macro expansion,
this rule is applied after the macro is expanded to find the appropriate place.
Places defined by using defmacro
or
define-setf-expander
use the evaluation order defined by those definitions.
For example, consider the following:
(defmacro wrong-order (x y) `(getf ,y ,x))
This following form evaluates place2
first and
then place1
because that is the order they are evaluated in
the macro expansion:
(push value (wrong-order place1 place2))
push
,
pushnew
,
remf
,
incf
,
decf
,
shiftf
,
rotatef
,
psetf
,
setf
,
pop
, and those defined by define-modify-macro
)
the subforms of the macro call are evaluated exactly once
in left-to-right order, with the subforms of the places
evaluated in the order specified in (1).
push
, pushnew
, remf
,
incf
, decf
, shiftf
, rotatef
,
psetf
, pop
evaluate all subforms before modifying
any of the place locations.
setf
(in the case when setf
has more than two arguments)
performs its operation on each pair in sequence. For example, in
(setf place1 value1 place2 value2 ...)
the subforms of place1
and value1
are evaluated, the location
specified by
place1
is modified to contain the value returned by
value1
, and
then the rest of the setf
form is processed in a like manner.
check-type
, ctypecase
, and ccase
,
subforms of the place are evaluated once as in (1),
but might be evaluated again if the
type check fails in the case of check-type
or none of the cases hold in
ctypecase
and ccase
.
assert
, the order of evaluation of the generalized
references is not specified.
Rules 2, 3 and 4 cover all standardized macros that manipulate places.
(let ((ref2 (list '()))) (push (progn (princ "1") 'ref-1) (car (progn (princ "2") ref2)))) ▷ 12 → (REF1) (let (x) (push (setq x (list 'a)) (car (setq x (list 'b)))) x) → (((A) . B))
push
first evaluates (setq x (list 'a))
→ (a)
,
then evaluates (setq x (list 'b))
→ (b)
,
then modifies the car of this latest value to be ((a) . b)
.
Sometimes it is possible to avoid evaluating subforms of a place multiple times or in the wrong order. A setf expansion for a given access form can be expressed as an ordered collection of five objects:
a list of symbols naming temporary variables to be bound
sequentially, as if by let*
, to values
resulting from value forms.
a list of forms (typically, subforms of the
place) which when evaluated
yield the values to which the corresponding temporary
variables should be bound.
a list of symbols naming temporary store variables which are
to hold the new values that will be assigned to the
place.
a form which can reference both the temporary and the store variables,
and which changes the value of the place
and guarantees to return as its values the values of the store variables,
which are the correct values for setf
to return.
a form which can reference the temporary variables, and which returns the value of the place.
The value returned by the accessing form is affected by execution of the storing form, but either of these forms might be evaluated any number of times.
It is possible
to do more than one setf
in parallel via
psetf
, shiftf
, and rotatef
.
Because of this, the
setf expander
must produce new temporary
and store variable names every time. For examples of how to do this,
see gensym
.
For each standardized accessor function F,
unless it is explicitly documented otherwise,
it is implementation-dependent whether the ability to
use an F form as a setf
place
is implemented by a setf expander or a setf function.
Also, it follows from this that it is implementation-dependent
whether the name (setf
F)
is fbound.
Examples of the contents of the constituents of setf expansions follow.
For a variable x:
|
Figure 5.3: Sample Setf Expansion of a Variable
For (car
exp)
:
|
Figure 5.4: Sample Setf Expansion of a CAR Form
For (subseq
seq s e)
:
|
Figure 5.5: Sample Setf Expansion of a SUBSEQ Form
In some cases, if a subform of a place is itself
a place, it is necessary to expand the subform
in order to compute some of the values in the expansion of the outer
place. For (ldb
bs (car
exp))
: