Is it possible to alter equality predicate of
setf in a a declarative way (without tons of elisp)?
See the docstring of
alist-get is a compiled Lisp function in ‘subr.el’.
(alist-get KEY ALIST &optional DEFAULT REMOVE TESTFN)
Probably introduced at or before Emacs version 25.1.
Find the first element of ALIST whose ‘car’ equals KEY and return its ‘cdr’.
If KEY is not found in ALIST, return DEFAULT.
Equality with KEY is tested by TESTFN, defaulting to ‘eq’.
You can use ‘alist-get’ in PLACE expressions. This will modify
an existing association (more precisely, the first one if
multiple exist), or add a new element to the beginning of ALIST,
destructively modifying the list stored in ALIST.
(setq foo '((a . 0)))
(setf (alist-get 'a foo) 1
(alist-get 'b foo) 2)
foo => ((b . 2) (a . 1))
When using it to set a value, optional argument REMOVE non-nil
means to remove KEY from ALIST if the new value is ‘eql’ to
DEFAULT (more precisely the first found association will be
deleted from the alist).
(setq foo '((a . 1) (b . 2)))
(setf (alist-get 'b foo nil 'remove) nil)
foo => ((a . 1))
The key point to note is the
TESTFN argument, which defaults to
eq but can also be set to
(setf (alist-get "a" alist nil nil #'equal) 1)
(setf (alist-get "a" alist nil nil #'equal) 2)
alist) ; => (("a" . 2))