Previous: Obsolete Macros, Up: Obsolete Features [Contents][Index]
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 Adding Generalized Variables in GNU Emacs Lisp Reference Manual.
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 (cl-once-only ((v (or n 1))) (funcall setter `(+ ,v ,getter)))))
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)
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))
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:
gensym
).
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.
Previous: Obsolete Macros, Up: Obsolete Features [Contents][Index]