File: gv.el.html
This is a re-implementation of the setf machinery using a different
underlying approach from the one used earlier in CL, which was based on
define-setf-expander.
define-setf-expander makes every "place-expander" return a 5-tuple
(VARS VALUES STORES GETTER SETTER)
where STORES is a list with a single variable (Common-Lisp allows multiple
variables for use with multiple-return-values, but this is rarely used and
not applicable to Elisp).
It basically says that GETTER is an expression that returns the place's
value, and (lambda STORES SETTER) is an expression that assigns the value(s)
passed to that function to the place, and that you need to wrap the whole
thing within a `(let* ,(zip VARS VALUES) ...).
Instead, we use here a higher-order approach: instead
of a 5-tuple, a place-expander returns a function.
If you think about types, the old approach returns things of type
{vars: List Var, values: List Exp,
stores: List Var, getter: Exp, setter: Exp}
whereas the new approach returns a function of type
(do: ((getter: Exp, setter: ((store: Exp) -> Exp)) -> Exp)) -> Exp.
You can get the new function from the old 5-tuple with something like:
(lambda (do)
(let* ,(zip VARS VALUES)
(funcall do GETTER (lambda ,STORES ,SETTER))))
You cant easily do the reverse, because this new approach is more
expressive than the old one, so we can't provide a backward-compatible
get-setf-method.
While it may seem intimidating for people not used to higher-order
functions, you will quickly see that its use (especially with the
gv-letplace macro) is actually much easier and more elegant than the old
approach which is clunky and often leads to unreadable code.
Food for thought: the syntax of places does not actually conflict with the
pcase patterns. The cons gv works just like a `(,a . ,b) pcase
pattern, and actually the logand gv is even closer since it should
arguably fail when trying to set a value outside of the mask.
Generally, places are used for destructors (gethash, aref, car, ...)
whereas pcase patterns are used for constructors (backquote, constants,
vectors, ...).
Defined variables (0)
Defined functions (19)
decf | (PLACE &optional DELTA) |
gv--defsetter | (NAME SETTER DO ARGS &optional VARS) |
gv--defun-declaration | (SYMBOL NAME ARGS HANDLER &optional FIX) |
gv--expander-defun-declaration | (&rest ARGS) |
gv--setter-defun-declaration | (&rest ARGS) |
gv-define-expander | (NAME HANDLER) |
gv-define-setter | (NAME ARGLIST &rest BODY) |
gv-define-simple-setter | (NAME SETTER &optional FIX-RETURN) |
gv-delay-error | (PLACE) |
gv-deref | (REF) |
gv-get | (PLACE DO) |
gv-letplace | ((GETTER SETTER) PLACE &rest BODY) |
gv-ref | (PLACE) |
gv-setter | (NAME) |
gv-synthetic-place | (GETTER SETTER) |
gv-synthetic-place--anon-cmacro | (_ GETTER SETTER) |
incf | (PLACE &optional DELTA) |
make-obsolete-generalized-variable | (OBSOLETE-NAME CURRENT-NAME WHEN) |
setf | (PLACE VAL PLACE VAL ...) |