cl: Obsolete Setf Customization

 
 D.3 Obsolete Ways to Customize Setf
 ===================================
 
 Common Lisp defines three macros, ‘define-modify-macro’, ‘defsetf’, and
 ‘define-setf-method’, that allow the user to extend generalized
 variables in various ways.  In Emacs, these are obsolete, replaced by
 various features of ‘gv.el’ in Emacs 24.3.  See(elisp)Adding
 Generalized Variables.
 
  -- Macro: define-modify-macro name arglist function [doc-string]
      This macro defines a “read-modify-write” macro similar to ‘cl-incf’
      and ‘cl-decf’.  You can replace this macro with ‘gv-letplace’.
 
      The macro NAME is defined to take a PLACE argument followed by
      additional arguments described by ARGLIST.  The call
 
           (NAME PLACE ARGS...)
 
      will be expanded to
 
           (cl-callf FUNC PLACE ARGS...)
 
      which in turn is roughly equivalent to
 
           (setf PLACE (FUNC PLACE ARGS...))
 
      For example:
 
           (define-modify-macro incf (&optional (n 1)) +)
           (define-modify-macro concatf (&rest args) concat)
 
      Note that ‘&key’ is not allowed in ARGLIST, but ‘&rest’ is
      sufficient to pass keywords on to the function.
 
      Most of the modify macros defined by Common Lisp do not exactly
      follow the pattern of ‘define-modify-macro’.  For example, ‘push’
      takes its arguments in the wrong order, and ‘pop’ is completely
      irregular.
 
      The above ‘incf’ example could be written using ‘gv-letplace’ as:
           (defmacro incf (place &optional n)
             (gv-letplace (getter setter) place
               (macroexp-let2 nil v (or n 1)
                 (funcall setter `(+ ,v ,getter)))))
 
  -- Macro: defsetf access-fn update-fn
      This is the simpler of two ‘defsetf’ forms, and is replaced by
      ‘gv-define-simple-setter’.
 
      With ACCESS-FN the name of a function that accesses a place, this
      declares UPDATE-FN to be the corresponding store function.  From
      now on,
 
           (setf (ACCESS-FN ARG1 ARG2 ARG3) VALUE)
 
      will be expanded to
 
           (UPDATE-FN ARG1 ARG2 ARG3 VALUE)
 
      The UPDATE-FN is required to be either a true function, or a macro
      that evaluates its arguments in a function-like way.  Also, the
      UPDATE-FN is expected to return VALUE as its result.  Otherwise,
      the above expansion would not obey the rules for the way ‘setf’ is
      supposed to behave.
 
      As a special (non-Common-Lisp) extension, a third argument of ‘t’
      to ‘defsetf’ says that the return value of ‘update-fn’ is not
      suitable, so that the above ‘setf’ should be expanded to something
      more like
 
           (let ((temp VALUE))
             (UPDATE-FN ARG1 ARG2 ARG3 temp)
             temp)
 
      Some examples are:
 
           (defsetf car setcar)
           (defsetf buffer-name rename-buffer t)
 
      These translate directly to ‘gv-define-simple-setter’:
 
           (gv-define-simple-setter car setcar)
           (gv-define-simple-setter buffer-name rename-buffer t)
 
  -- Macro: defsetf access-fn arglist (store-var) forms...
      This is the second, more complex, form of ‘defsetf’.  It can be
      replaced by ‘gv-define-setter’.
 
      This form of ‘defsetf’ is rather like ‘defmacro’ except for the
      additional STORE-VAR argument.  The FORMS should return a Lisp form
      that stores the value of STORE-VAR into the generalized variable
      formed by a call to ACCESS-FN with arguments described by ARGLIST.
      The FORMS may begin with a string which documents the ‘setf’ method
      (analogous to the doc string that appears at the front of a
      function).
 
      For example, the simple form of ‘defsetf’ is shorthand for
 
           (defsetf ACCESS-FN (&rest args) (store)
             (append '(UPDATE-FN) args (list store)))
 
      The Lisp form that is returned can access the arguments from
      ARGLIST and STORE-VAR in an unrestricted fashion; macros like
      ‘cl-incf’ that invoke this setf-method will insert temporary
      variables as needed to make sure the apparent order of evaluation
      is preserved.
 
      Another standard example:
 
           (defsetf nth (n x) (store)
             `(setcar (nthcdr ,n ,x) ,store))
 
      You could write this using ‘gv-define-setter’ as:
 
           (gv-define-setter nth (store n x)
             `(setcar (nthcdr ,n ,x) ,store))
 
  -- Macro: define-setf-method access-fn arglist forms...
      This is the most general way to create new place forms.  You can
      replace this by ‘gv-define-setter’ or ‘gv-define-expander’.
 
      When a ‘setf’ to ACCESS-FN with arguments described by ARGLIST is
      expanded, the FORMS are evaluated and must return a list of five
      items:
 
        1. A list of “temporary variables”.
 
        2. A list of “value forms” corresponding to the temporary
           variables above.  The temporary variables will be bound to
           these value forms as the first step of any operation on the
           generalized variable.
 
        3. A list of exactly one “store variable” (generally obtained
           from a call to ‘gensym’).
 
        4. A Lisp form that stores the contents of the store variable
           into the generalized variable, assuming the temporaries have
           been bound as described above.
 
        5. A Lisp form that accesses the contents of the generalized
           variable, assuming the temporaries have been bound.
 
      This is exactly like the Common Lisp macro of the same name, except
      that the method returns a list of five values rather than the five
      values themselves, since Emacs Lisp does not support Common Lisp’s
      notion of multiple return values.  (Note that the ‘setf’
      implementation provided by ‘gv.el’ does not use this five item
      format.  Its use here is only for backwards compatibility.)
 
      Once again, the FORMS may begin with a documentation string.
 
      A setf-method should be maximally conservative with regard to
      temporary variables.  In the setf-methods generated by ‘defsetf’,
      the second return value is simply the list of arguments in the
      place form, and the first return value is a list of a corresponding
      number of temporary variables generated by ‘cl-gensym’.  Macros
      like ‘cl-incf’ that use this setf-method will optimize away most
      temporaries that turn out to be unnecessary, so there is little
      reason for the setf-method itself to optimize.