User Tools

A PCRE internal error occured. This might be caused by a faulty plugin

====== Macro DEFSETF ====== ====Syntax==== The "short form": * **defsetf** //access-fn update-fn [documentation]// → //access-fn// The "long form": * **defsetf** //access-fn lambda-list (store-variable''*'') <nowiki>[[</nowiki>declaration''*'' | documentation<nowiki>]]</nowiki> form''*''// → //access-fn// ====Arguments and Values==== * //access-fn// - a //[[CL:Glossary:symbol]]// which names a //[[CL:Glossary:function]]// or a //[[CL:Glossary:macro]]//. * //update-fn// - a //[[CL:Glossary:symbol]]// naming a //[[CL:Glossary:function]]// or //[[CL:Glossary:macro]]//. * //lambda-list// - a //[[CL:Glossary:defsetf lambda list]]//. * //store-variable// - a //[[CL:Glossary:symbol]]// (a //[[CL:Glossary:variable]]// //[[CL:Glossary:name]]//). * //declaration// - a **[[CL:Special Operators:declare]]** //[[CL:Glossary:expression]]//; not evaluated. * //documentation// - a //[[CL:Glossary:string]]//; not evaluated. * //form// - a //[[CL:Glossary:form]]//. ====Description==== **defsetf** defines how to **[[CL:Macros:setf]]** a //[[CL:Glossary:place]]// of the form ''(access-fn ...)'' for relatively simple cases. (See **[[CL:Macros:define-setf-expander]]** for more general access to this facility.) It must be the case that the //[[CL:Glossary:function]]// or //[[CL:Glossary:macro]]// named by //access-fn// evaluates all of its arguments. **defsetf** may take one of two forms, called the "short form" and the "long form," which are distinguished by the //[[CL:Glossary:type]]// of the second //[[CL:Glossary:argument]]//. When the short form is used, //update-fn// must name a //[[CL:Glossary:function]]// (or //[[CL:Glossary:macro]]//) that takes one more argument than //access-fn// takes. When **[[CL:Macros:setf]]** is given a //[[CL:Glossary:place]]// that is a call on //access-fn//, it expands into a call on //update-fn// that is given all the arguments to //access-fn// and also, as its last argument, the new value (which must be returned by //update-fn// as its value). The long form **defsetf** resembles **[[CL:Macros:defmacro]]**. The //lambda-list// describes the arguments of //access-fn//. The //store-variables// describe the value or values to be stored into the //[[CL:Glossary:place]]//. The //body// must compute the expansion of a **[[CL:Macros:setf]]** of a call on //access-fn//. The expansion function is defined in the same //[[CL:Glossary:lexical environment]]// in which the **defsetf** //[[CL:Glossary:form]]// appears. During the evaluation of the //forms//, the variables in the //lambda-list// and the //store-variables// are bound to names of temporary variables, generated as if by **[[CL:Functions:gensym]]** or **[[CL:Functions:gentemp]]**, that will be bound by the expansion of **[[CL:Macros:setf]]** to the values of those //[[CL:Glossary:subforms]]//. This binding permits the //forms// to be written without regard for order-of-evaluation issues. **defsetf** arranges for the temporary variables to be optimized out of the final result in cases where that is possible. The body code in **defsetf** is implicitly enclosed in a //[[CL:Glossary:block]]// whose name is //access-fn//. **defsetf** ensures that //[[CL:Glossary:subforms]]// of the //[[CL:Glossary:place]]// are evaluated exactly once. //documentation// is attached to //access-fn// as a //[[CL:Glossary:documentation string]]// of kind **[[CL:Types:setf]]**. If a **defsetf** //[[CL:Glossary:form]]// appears as a //[[CL:Glossary:top level form]]//, the //[[CL:Glossary:compiler]]// must make the //[[CL:Glossary:setf expander]]// available so that it may be used to expand calls to **[[CL:Macros:setf]]** later on in the //[[CL:Glossary:file]]//. Users must ensure that the //forms//, if any, can be evaluated at compile time if the //access-fn// is used in a //[[CL:Glossary:place]]// later in the same //[[CL:Glossary:file]]//. The //[[CL:Glossary:compiler]]// must make these //[[CL:Glossary:setf expander|setf expanders]]// available to compile-time calls to **[[CL:Functions:get-setf-expansion]]** when its //environment// argument is a value received as the //[[CL:Glossary:environment parameter]]// of a //[[CL:Glossary:macro]]//. ====Examples==== The effect of ''(defsetf [[CL:Functions:symbol-value]] [[CL:Functions:set]])'' is built into the Common Lisp system. This causes the form ''([[CL:Macros:setf]] ([[CL:Functions:symbol-value]] foo) fu)'' to expand into ''([[CL:Functions:set]] foo fu)''. Note that ''(defsetf car rplaca)'' would be incorrect because **[[CL:Functions:rplaca]]** does not return its last argument. <blockquote> ([[CL:Macros:defun]] middleguy (x) ([[CL:Functions:nth]] ([[CL:Functions:truncate]] ([[CL:Functions:math-one-minus|1-]] ([[CL:Functions:list-length]] x)) 2) x)) <r>MIDDLEGUY</r> ([[CL:Macros:defun]] set-middleguy (x v) ([[CL:Macros:unless]] ([[CL:Functions:null]] x) ([[CL:Functions:rplaca]] ([[CL:Functions:nthcdr]] ([[CL:Functions:truncate]] ([[CL:Functions:math-one-minus|1-]] ([[CL:Functions:list-length]] x)) 2) x) v)) v) <r>SET-MIDDLEGUY</r> (defsetf middleguy set-middleguy) <r>MIDDLEGUY </r> ([[CL:Macros:defparameter]] *a* ([[CL:Functions:list]] 'a 'b 'c 'd)) <r>*A*</r> ([[CL:Macros:defparameter]] *b* ([[CL:Functions:list]] 'x)) <r>*B*</r> ([[CL:Macros:defparameter]] *c* ([[CL:Functions:list]] 1 2 3 ([[CL:Functions:list]] 4 5 6) 7 8 9)) <r>*C*</r> ([[CL:Macros:setf]] (middleguy *a*) 3) <r>3 </r> ([[CL:Macros:setf]] (middleguy *b*) 7) <r>7 </r> ([[CL:Macros:setf]] (middleguy (middleguy *c*)) 'middleguy-symbol) <r>MIDDLEGUY-SYMBOL </r> *a* <r>(A 3 C D) </r> *b* <r>(7) </r> *c* <r>(1 2 3 (4 MIDDLEGUY-SYMBOL 6) 7 8 9) </r> </blockquote> An example of the use of the long form of **defsetf**: <blockquote> (defsetf subseq (sequence start &optional end) (new-sequence) `(progn (replace ,sequence ,new-sequence :start1 ,start :end1 ,end) ,new-sequence)) <r>SUBSEQ</r> </blockquote> <blockquote> ;;; TODO this example is terrible, replace it ([[CL:Macros:defvar]] *xy* ([[CL:Functions:make-array]] '(10 10))) <r>*XY*</r> ([[CL:Macros:defun]] xy (&key ((x x) 0) ((y y) 0)) ([[CL:Functions:aref]] *xy* x y)) <r>XY</r> ([[CL:Macros:defun]] set-xy (new-value &key ((x x) 0) ((y y) 0)) ([[CL:Macros:setf]] ([[CL:Functions:aref]] *xy* x y) new-value)) <r>SET-XY</r> (defsetf xy (&key ((x x) 0) ((y y) 0)) (store) `(set-xy ,store 'x ,x 'y ,y)) <r>XY</r> ([[CL:Functions:get-setf-expansion]] '(xy a b)) <r>(#:t0 #:t1) (a b) (#:store) (([[CL:Symbols:lambda]] (&key ((x #:x)) ((y #:y))) (set-xy #:store 'x #:x 'y #:y)) #:t0 #:t1) (xy #:t0 #:t1)</r> (xy 'x 1) <r>[[CL:Constant Variables:NIL]]</r> ([[CL:Macros:setf]] (xy 'x 1) 1) <r>1 </r> (xy 'x 1) <r>1 </r> ([[CL:Special Operators:let]] ((a 'x) (b 'y)) ([[CL:Macros:setf]] (xy a 1 b 2) 3) ([[CL:Macros:setf]] (xy b 5 a 9) 14)) <r>14 </r> (xy 'y 0 'x 1) <r>1 </r> (xy 'x 1 'y 2) <r>3 </r> </blockquote> An example involving //[[CL:Glossary:structure|structures]]// and //[[CL:Glossary:multiple values]]// in **defsetf**: <blockquote> ([[CL:Macros:defstruct]] point x y z) <r>POINT</r> ([[CL:Macros:defsetf]] foo (point &key kind) (x y z) `([[CL:Macros:ecase]] ,kind (:2d ([[CL:Macros:setf]] ([[CL:Functions:values]] (point-x ,point) (point-y ,point)) ([[CL:Functions:values]] ,x ,y))) (:3d ([[CL:Macros:setf]] ([[CL:Functions:values]] (point-x ,point) (point-y ,point) (point-z ,point)) ([[CL:Functions:values]] ,x ,y ,z))))) <r>FOO</r> ([[CL:Macros:defvar]] *point-1* (make-point)) <r>*POINT-1*</r> ([[CL:Macros:defvar]] *point-2* (make-point)) <r>*POINT-2*</r> ([[CL:Macros:setf]] (foo *point-1* :kind :2d) ([[CL:Functions:values]] 1 2)) <r>1 2</r> ([[CL:Macros:setf]] (foo *point-2* :kind :3d) ([[CL:Functions:values]] 8 9 10)) <r>8 9 10</r> *point-1* <r>#S(POINT :X 1 :Y 2 :Z NIL)</r> *point-2* <r>#S(POINT :X 8 :Y 9 :Z 10)</r> </blockquote> ====Affected By==== None. ====Exceptional Situations==== None. ====See Also==== * **[[CL:Functions:documentation|Generic Function DOCUMENTATION]]** * **[[CL:Macros:setf|Macro SETF]]** * **[[CL:Macros:define-setf-expander|Macro DEFINE-SETF-EXPANDER]]** * **[[CL:Functions:get-setf-expansion|Function GET-SETF-EXPANSION]]** * {\secref\GeneralizedReference} * {\secref\DocVsDecls} ====Notes==== //forms// must include provision for returning the correct value (the value or values of //store-variable//). This is handled by //forms// rather than by **defsetf** because in many cases this value can be returned at no extra cost, by calling a function that simultaneously stores into the //[[CL:Glossary:place]]// and returns the correct value. A **[[CL:Macros:setf]]** of a call on //access-fn// also evaluates all of //access-fn//'s arguments; it cannot treat any of them specially. This means that **defsetf** cannot be used to describe how to store into a //[[CL:Glossary:generalized reference]]// to a byte, such as ''(ldb field reference)''. **[[CL:Macros:define-setf-expander]]** is used to handle situations that do not fit the restrictions imposed by **defsetf** and gives the user additional control. \issue{SETF-METHOD-VS-SETF-METHOD:RENAME-OLD-TERMS} \issue{SETF-MULTIPLE-STORE-VARIABLES:ALLOW} \issue{SETF-METHOD-VS-SETF-METHOD:RENAME-OLD-TERMS} \issue{DECLS-AND-DOC} \issue{KMP-COMMENTS-ON-SANDRA-COMMENTS:X3J13-MAR-92} \issue{SETF-MULTIPLE-STORE-VARIABLES:ALLOW} \issue{DEFINING-MACROS-NON-TOP-LEVEL:ALLOW} \issue{FLET-IMPLICIT-BLOCK:YES} \issue{COMPILE-FILE-HANDLING-OF-TOP-LEVEL-FORMS:CLARIFY}