A function form can be used as a place if it falls into one of the following categories:
[Editorial Note by KMP: Note that what are in some places still called `condition accessors' are deliberately omitted from this table, and are not labeled as accessors in their entries. I have not yet had time to do a full search for these items and eliminate stray references to them as `accessors', which they are not, but I will do that at some point.]
aref cdadr get bit cdar gethash caaaar cddaar logical-pathname-translations caaadr cddadr macro-function caaar cddar ninth caadar cdddar nth caaddr cddddr readtable-case caadr cdddr rest caar cddr row-major-aref cadaar cdr sbit cadadr char schar cadar class-name second caddar compiler-macro-function seventh cadddr documentation sixth caddr eighth slot-value cadr elt subseq car fdefinition svref cdaaar fifth symbol-function cdaadr fill-pointer symbol-plist cdaar find-class symbol-value cdadar first tenth cdaddr fourth third 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.
The function name must refer to the global function definition,
rather than a locally defined function.
Function name Argument that is a place Update function used ldb second dpb mask-field second deposit-field getf first implementation-dependent 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.
(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:
its value or values into the store variable).
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.
(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:
its value or values into the store variable).
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.