Moon thinks terms "generalized reference" and "place" need to be rationalized throughout. Done! -kmp 16-Jul-93
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. 7.2.0 18In 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 7.2.0 19 that the ultimate result of evaluating setf is the value or values being stored.
| Access function | Update Function | Update using setf |
x | (setq x datum) | (setf x datum) |
(car x) | (rplaca x datum) | (setf (car x) datum) |
(symbol-value x) | (set x datum) | (setf (symbol-value x) datum) |
Figure 5–1. Examples of setf
The next figure shows operators relating to places and generalized reference.
assert | defsetf | push |
ccase | get-setf-expansion | remf |
ctypecase | getf | rotatef |
decf | incf | setf |
define-modify-macro | pop | shiftf |
define-setf-expander | psetf |
Figure 5–2. Operators relating to places and generalized reference.
!!! Should defmethod be here for the sake of SETF methods?? -kmp 8-May-91
Some of the operators above manipulate places and some manipulate setf expanders. 7.2.0 57A setf expansion can be derived from any place. 7.2.0 20New setf expanders can be defined by using defsetf and define-setf-expander.
Moon thinks this follows from rule 2 below, and asked that it be commented out. 7.2.0 29 7.2.0 30 These operators evaluate the \term{subforms} of \term{places} exactly as many times as they appear in the source program, and exactly in the same order (left-to-right) as they appear in the source. \issue{PUSH-EVALUATION-ORDER:ITEM-FIRST} The left-to-right rule does not remove the obligation on writers of \term{macros} and users of \issue{SETF-METHOD-VS-SETF-METHOD:RENAME-OLD-TERMS} \macref{define-setf-expander} \endissue{SETF-METHOD-VS-SETF-METHOD:RENAME-OLD-TERMS} to ensure left-to-right order, however. \endissue{PUSH-EVALUATION-ORDER:ITEM-FIRST} 7.2.0 31 For example, in {\tt (setf \param{reference} \param{value})} \param{value} will be evaluated after all the \term{subforms} of \param{reference} because \param{value} appears to the right of them.
7.2.0 32 The expansion of these operators must consist of code that follows these rules or has the same effect as such code. This is accomplished by introducing temporary variables bound to the \issue{PUSH-EVALUATION-ORDER:ITEM-FIRST} \term{subforms} of the macro call. \endissue{PUSH-EVALUATION-ORDER:ITEM-FIRST} As an optimization in the implementation, temporary variables can be eliminated whenever removing them has no effect on the semantics of the program. For example, a constant need never be saved in a temporary variable. A variable or any \term{form} that does not have side effects need not be saved in a temporary variable if it can be proven that its value will not change within the scope of the \term{place}.
The following rules apply to the evaluation of subforms in a place:
get-setf-expansion. For all places defined by this specification !!! Table??(e.g., getf, ldb, ), this order of evaluation is left-to-right. !!! Barmar: Does the next sentence say the same thing as the one which follows it
(i.e., the first sentence in the next paragraph)??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. Barmar: There's only one place in \macref{assert}.
Moon: Not true!
(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).
!!! Uses of "access", "accessing", etc. here are suspect. -kmp 18-Apr-91
7.2.0 59Sometimes 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:
!!! Andy Latto is concerned about whether "temporaries" mustn't or might be proclaimed special. And if they must not, must an implementation check? Would some elaboration of what a "temporary" is here be of help? -kmp 5-Dec-91
7.2.0 60
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.
7.2.0 61 7.2.0 65
a list of symbols naming temporary store variables which are to hold the new values that will be assigned to the place.
7.2.0 62
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.
7.2.0 63
a form which can reference the temporary variables, and which returns the value of the place.
7.2.0 66The 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.
7.2.0 67 Redundant with next paragraph. The temporary variables and the store variables must be generated names (see \funref{gensym} or \funref{gentemp}).
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. and \funref{gentemp}.
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.
7.2.0 69For a variable x:
() | ;list of temporary variables |
() | ;list of value forms |
(g0001) | ;list of store variables |
(setq x g0001) | ;storing form |
| x | ;accessing form |
Figure 5–3. Sample Setf Expansion of a Variable
7.2.0 70For (car exp):
(g0002) | ;list of temporary variables |
(exp) | ;list of value forms |
(g0003) | ;list of store variables |
(progn (rplaca g0002 g0003) g0003) | ;storing form |
(car g0002) | ;accessing form |
Figure 5–4. Sample Setf Expansion of a CAR Form
7.2.0 71For (subseq seq s e):
(g0004 g0005 g0006) | ;list of temporary variables |
(seq s e) | ;list of value forms |
(g0007) | ;list of store variables |
(progn (replace g0004 g0007 :start1 g0005 :end1 g0006) g0007) | |
| ;storing form | |
(subseq g0004 g0005 g0006) | ; accessing form |
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)):
(g0001 g0002) | ;list of temporary variables |
(bs exp) | ;list of value forms |
(g0003) | ;list of store variables |
(progn (rplaca g0002 (dpb g0003 g0001 (car g0002))) g0003) | |
| ;storing form | |
(ldb g0001 (car g0002)) | ; accessing form |
Figure 5–6. Sample Setf Expansion of a LDB Form
7.2.0 7Several kinds of places are defined by Common Lisp; this section enumerates them. This set can be extended by implementations and by programmer code.
7.2.0 8
7.2.0 9
A function form can be used as a place if it falls into one of the following categories:
!!! CLASS-NAME and DOCUMENTATION maybe deserve their own table, since they are the only two defined by setf method.
Editor: 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.!!! Merged BIT, SBIT, CHAR, SCHAR, and SUBSEQ from next table on advice of Moon and others. -kmp 13-Feb-92 I added COMPILER-MACRO-FUNCTION, READTABLE-CASE, and SLOT-VALUE, which were also missing. --sjl 5 Mar 92
Figure 5–7. Functions that setf can be used with—1
This text used to belong after the next table, which is now commented out. -kmp 13-Feb-92In 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 !!! Moon thinks this next is awkward.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. Barmar: Unnecessary as binding these symbols is disallowed.
KMP: I'm not so sure in this case. The function name must refer to the global function definition, rather than a locally defined function.
Moon: The distinction between this and the previous table is strange. After all, fill-pointer, symbol-function, and class-name have type restrictions, too. Also, the text above this table seems garbled. I would merge these into previous and delete the text. KMP: Done. (13-Feb-92) \itemitem{\bull} 7.2.0 11 A function call form whose first element is the name of any one of the functions in \thenextfigure, provided that the new value is of the specified type so that it can be used to place in the specified ``location'' (which is in each of these cases not truly a \term{place}). Barmar: Unnecessary as binding these symbols is disallowed. \issue{FUNCTION-NAME:LARGE} The function name must refer to the global function definition, rather than a locally defined \term{function}. \endissue{FUNCTION-NAME:LARGE} \issue{CHARACTER-PROPOSAL:2-1-1} \tablefigtwo{Functions that setf can be used with---n}{Function name}{Required type}{ \funref{bit}&\typeref{bit} \funref{sbit}&\typeref{bit} \funref{char}&\typeref{character} \funref{schar}&\typeref{character} \funref{subseq}&\typeref{sequence} } \endissue{CHARACTER-PROPOSAL:2-1-1}
| 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
Moon thinks this is redundant.
The \param{place} forms listed in the above figure admit other
\param{places} as arguments; these are called sub-recursive \param{places}.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:
(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:
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.
This section added. --sjl 4 Mar 92
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.
There probably ought to be some examples here.
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}*)
Removed reference to (setf (apply #'name a1 a2 ...) (values v1 v2 ...)) as bogus.
7.2.0 16
macroexpand-1 and then uses the macro expansion in place of the original place. This is true for GET-SETF-EXPANSION, too, but there's no obvious place to say that.
-kmp 5-Jun-91Such macro expansion is attempted only after exhausting all other possibilities other than expanding into a call to a function named (setf reader).
I moved this section here from below. --sjl 5 Mar 92
setf expands the reference and then analyzes the resulting form.
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.
I moved the symbol macro section up to be with the ordinary macro section. --sjl 5 Mar 92
For each of the “read-modify-write” operators in the next figure, and for any additional macros defined by the programmer using define-modify-macro, an exception is made to the normal rule of left-to-right evaluation of arguments. Evaluation of argument forms occurs in left-to-right order, with the exception that for the place argument, the actual read of the “old value” from that place happens after all of the argument form evaluations, and just before a “new value” is computed and written back into the place.
Specifically, each of these operators can be viewed as involving a form with the following general syntax:
(operator {preceding-form}* place {following-form}*)
The evaluation of each such form proceeds like this:
This text was originally duplicated in each of GO, RETURN-FROM, and THROW. I thought it would be less redundant to centralize it here. --sjl 7 Mar 92
When a transfer of control is initiated by go, return-from, or throw the following events occur in order to accomplish the transfer of control. Note that for go, the exit point is the form within the tagbody that is being executed at the time the go is performed; for return-from, the exit point is the corresponding block form; and for throw, the exit point is the corresponding catch form.
unwind-protect clauses are evaluated.
special variables, catch tags, condition handlers, and restarts are undone.
The extent of an exit being “abandoned” because it is being passed over ends as soon as the transfer of control is initiated. That is, event 1 occurs at the beginning of the initiation of the transfer of control. The consequences are undefined if an attempt is made to transfer control to an exit point whose dynamic extent has ended.
Moon had me add the part about "interleaved" -kmp 13-Feb-92Events 2 and 3 are actually performed interleaved, in the order corresponding to the reverse order in which they were established. The effect of this is that the cleanup clauses of an unwind-protect see the same dynamic bindings of variables and catch tags as were visible when the unwind-protect was entered.
Event 4 occurs at the end of the transfer of control.
apply Functiondefun Macrofdefinition Accessorfboundp Functionfmakunbound Functionflet, labels, macrolet Special Operatorfuncall Functionfunction Special Operatorfunction-lambda-expression Functionfunctionp Functioncompiled-function-p Functioncall-arguments-limit Constant Variablelambda-list-keywords Constant Variablelambda-parameters-limit Constant Variabledefconstant Macrodefparameter, defvar Macrodestructuring-bind Macrolet, let* Special Operatorprogv Special Operatorsetq Special Operatorpsetq Macroblock Special Operatorcatch Special Operatorgo Special Operatorreturn-from Special Operatorreturn Macrotagbody Special Operatorthrow Special Operatorunwind-protect Special Operatornil Constant Variablenot Functiont Constant Variableeq Functioneql Functionequal Functionequalp Functionidentity Functioncomplement Functionconstantly Functionevery, some, notevery, notany Functionand Macrocond Macroif Special Operatoror Macrowhen, unless Macrocase, ccase, ecase Macrotypecase, ctypecase, etypecase Macromultiple-value-bind Macromultiple-value-call Special Operatormultiple-value-list Macromultiple-value-prog1 Special Operatormultiple-value-setq Macrovalues Accessorvalues-list Functionmultiple-values-limit Constant Variablenth-value Macroprog, prog* Macroprog1, prog2 Macroprogn Special Operatordefine-modify-macro Macrodefsetf Macrodefine-setf-expander Macroget-setf-expansion Functionsetf, psetf Macroshiftf Macrorotatef Macrocontrol-error Condition Typeprogram-error Condition Typeundefined-function Condition Type