elisp: Adding Generalized Variables
11.15.2 Defining new ‘setf’ forms
---------------------------------
This section describes how to define new forms that ‘setf’ can operate
on.
-- Macro: gv-define-simple-setter name setter &optional fix-return
This macro enables you to easily define ‘setf’ methods for simple
cases. NAME is the name of a function, macro, or special form.
You can use this macro whenever NAME has a directly corresponding
SETTER function that updates it, e.g., ‘(gv-define-simple-setter
car setcar)’.
This macro translates a call of the form
(setf (NAME ARGS...) VALUE)
into
(SETTER ARGS... VALUE)
Such a ‘setf’ call is documented to return VALUE. This is no
problem with, e.g., ‘car’ and ‘setcar’, because ‘setcar’ returns
the value that it set. If your SETTER function does not return
VALUE, use a non-‘nil’ value for the FIX-RETURN argument of
‘gv-define-simple-setter’. This expands into something equivalent
to
(let ((temp VALUE))
(SETTER ARGS... temp)
temp)
so ensuring that it returns the correct result.
-- Macro: gv-define-setter name arglist &rest body
This macro allows for more complex ‘setf’ expansions than the
previous form. You may need to use this form, for example, if
there is no simple setter function to call, or if there is one but
it requires different arguments to the place form.
This macro expands the form ‘(setf (NAME ARGS...) VALUE)’ by first
binding the ‘setf’ argument forms ‘(VALUE ARGS...)’ according to
ARGLIST, and then executing BODY. BODY should return a Lisp form
that does the assignment, and finally returns the value that was
set. An example of using this macro is:
(gv-define-setter caar (val x) `(setcar (car ,x) ,val))
For more control over the expansion, see the macro
‘gv-define-expander’. The macro ‘gv-letplace’ can be useful in defining
macros that perform similarly to ‘setf’; for example, the ‘incf’ macro
of Common Lisp. Consult the source file ‘gv.el’ for more details.
Common Lisp note: Common Lisp defines another way to specify the
‘setf’ behavior of a function, namely ‘setf’ functions, whose names
are lists ‘(setf NAME)’ rather than symbols. For example, ‘(defun
(setf foo) ...)’ defines the function that is used when ‘setf’ is
applied to ‘foo’. Emacs does not support this. It is a
compile-time error to use ‘setf’ on a form that has not already had
an appropriate expansion defined. In Common Lisp, this is not an
error since the function ‘(setf FUNC)’ might be defined later.