Next: Treatment of Other Macros Based on SETF, Previous: Overview of Places and Generalized Reference, Up: Generalized Reference
Several kinds of places are defined by Common Lisp; this section enumerates them. This set can be extended by implementations and by programmer code.
The name of a lexical variable or dynamic variable can be used as a place.
A function form can be used as a place if it falls into one of the following categories:
|
Figure 5.7: Functions that setf can be used with—1
In the case of subseq
, the replacement value must be a sequence
whose elements might be contained by the sequence argument to subseq
,
but does not have to be a sequence of the same type
as the sequence of which the subsequence is specified.
If the length of the replacement value does not equal the length of
the subsequence to be replaced, then the shorter length determines
the number of elements to be stored, as for replace
.
defstruct
.
The function name must refer to the global function definition,
rather than a locally defined function.
|
Figure 5.8: Functions that setf can be used with—2
During the setf
expansion of these forms, it is necessary to call
get-setf-expansion
in order to figure out how the inner, nested generalized variable must be treated.
The information from
get-setf-expansion
is used as follows.
ldb
In a form such as:
(setf (ldb
byte-spec place-form)
value-form)
the place referred to by the place-form must always be both read
and written; note that the update is to the generalized variable
specified by place-form, not to any object of type integer
.
Thus this setf
should generate code to do the following:
If the evaluation of value-form in step 3 alters what is found in place-form, such as setting different bits of integer, then the change of the bits denoted by byte-spec is to that altered integer, because step 4 is done after the value-form evaluation. Nevertheless, the evaluations required for binding the temporary variables are done in steps 1 and 2, and thus the expected left-to-right evaluation order is seen. For example:
(setq integer #x69) → #x69 (rotatef (ldb (byte 4 4) integer) (ldb (byte 4 0) integer)) integer → #x96 ;;; This example is trying to swap two independent bit fields ;;; in an integer. Note that the generalized variable of ;;; interest here is just the (possibly local) program variable ;;; integer.
mask-field
This case is the same as ldb
in all essential aspects.
getf
In a form such as:
(setf (getf
place-form ind-form)
value-form)
the place referred to by place-form must always be both read and written; note that the update is to the generalized variable specified by place-form, not necessarily to the particular list that is the property list in question.
Thus this setf
should generate code to do the following:
If the evaluation of value-form in step 3 alters what is found in place-form, such as setting a different named property in the list, then the change of the property denoted by ind-form is to that altered list, because step 4 is done after the value-form evaluation. Nevertheless, the evaluations required for binding the temporary variables are done in steps 1 and 2, and thus the expected left-to-right evaluation order is seen.
For example:
(setq s (setq r (list (list 'a 1 'b 2 'c 3)))) → ((a 1 b 2 c 3)) (setf (getf (car r) 'b) (progn (setq r nil) 6)) → 6 r → NIL s → ((A 1 B 6 C 3)) ;;; Note that the (setq r nil) does not affect the actions of ;;; the SETF because the value of R had already been saved in ;;; a temporary variable as part of the step 1. Only the CAR ;;; of this value will be retrieved, and subsequently modified ;;; after the value computation.
A values
form can be used as a place,
provided that each of its subforms is also a place form.
A form such as
(setf (values
place-1 ...
place-n)
values-form)
does the following:
multiple-value-bind
.
nil
.
The storing form in the setf expansion of values
returns as multiple values2 the values of the store
variables in step 2. That is, the number of values returned is the
same as the number of place forms. This may be more or fewer
values than are produced by the values-form.
A the
form can be used as a place,
in which case the declaration is transferred to the newvalue form,
and the resulting setf
is analyzed. For example,
(setf (the integer (cadr x)) (+ y 3))
is processed as if it were
(setf (cadr x) (the integer (+ y 3)))
The following situations involving setf
of apply
must be supported:
(setf (apply #'aref
array
{subscript
}*
more-subscripts)
new-element)
(setf (apply #'bit
array
{subscript
}*
more-subscripts)
new-element)
(setf (apply #'sbit
array
{subscript
}*
more-subscripts)
new-element)
In all three cases, the element of array designated
by the concatenation of subscripts and more-subscripts
(i.e., the same element which would be read by the call to
apply if it were not part of a setf
form)
is changed to have the value given by new-element.
For these usages, the function name (aref
, bit
, or sbit
)
must refer to the global function definition, rather than a locally defined
function.
No other standardized function is required to be supported, but an implementation may define such support. An implementation may also define support for implementation-defined operators.
If a user-defined function is used in this context, the following equivalence is true, except that care is taken to preserve proper left-to-right evaluation of argument subforms:
(setf (apply #'name {arg}*) val) ≡ (apply #'(setf name) val {arg}*)
Any compound form for which the operator has a setf expander defined can be used as a place. The operator must refer to the global function definition, rather than a locally defined function or macro.
A macro form can be used as a place,
in which case Common Lisp expands the macro form
as if by macroexpand-1
and then uses the macro expansion in place of the original place.
Such macro expansion is attempted only after exhausting all other possibilities
other than expanding into a call to a function named (setf
reader)
.
A reference to a symbol that has been established as a symbol macro
can be used as a place. In this case,
setf
expands the reference and then analyzes the resulting form.
For any other compound form for which the operator is a
symbol f,
the setf
form expands into a call
to the function named (setf
f)
.
The first argument in the newly constructed function form
is newvalue and the
remaining arguments are the remaining elements of
place.
This expansion occurs regardless of whether f or (setf
f)
is defined as a function locally, globally, or not at all.
For example,
(setf (
f arg1 arg2 ...)
new-value)
expands into a form with the same effect and value as
(let ((#:temp-1 arg1) ;force correct order of evaluation (#:temp-2 arg2) ... (#:temp-0 new-value)) (funcall (function (setf f)) #:temp-0 #:temp-1 #:temp-2...))
A function named (setf
f)
must return its first argument
as its only value in order to preserve the semantics of setf
.