Next: , Up: Generalized Reference


5.1.1 Overview of Places and Generalized Reference

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.

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.

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.

5.1.1.1 Evaluation of Subforms to Places

The following rules apply to the evaluation of subforms in a place:

  1. The evaluation ordering of subforms within a place is determined by the order specified by the second value returned by 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))
    
  2. For the macros that manipulate places (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.

  3. For 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.
  4. For assert, the order of evaluation of the generalized references is not specified.

Rules 2, 3 and 4 cover all standardized macros that manipulate places.

5.1.1.1.1 Examples of Evaluation of Subforms to 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).

5.1.1.2 Setf Expansions

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:

List of temporary variables

a list of symbols naming temporary variables to be bound sequentially, as if by let*, to values resulting from value forms.

List of 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.

List of store variables

a list of symbols naming temporary store variables which are to hold the new values that will be assigned to the place.

Storing form

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.

Accessing form

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.

5.1.1.2.1 Examples of Setf Expansions

Examples of the contents of the constituents of setf expansions follow.

For 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

For (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

For (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