Is it possible to alter equality predicate of setf
in a a declarative way (without tons of elisp)?
See the docstring of alist-get
:
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.
Example:
(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).
Example:
(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 equal
:
(let (alist)
(setf (alist-get "a" alist nil nil #'equal) 1)
(setf (alist-get "a" alist nil nil #'equal) 2)
alist) ; => (("a" . 2))
alist-get
useseq
for testing by default, check its docstring.