Subject: Re: add-to-alist: new function

From: Stephen Gildea <[email-masked]>
Date: Tue, 21 Jan 2025 13:11:33 -0800

Yes, all these years later, I still use my add-to-alist.
It would be great to get this moved into Emacs proper and out
of my init file.  That this issue keeps popping up says to me
that other people also would like this functionality to be
easily available.

What I like about it is how easy it is to read at the call site.

And, as has been discussed here, none of the proposed
replacements has the option to do nothing if the key is
already present (the NO-REPLACE argument).  I use this option
in most of the calls in my init file, and I think it is the
compelling value-add over add-to-list.

What I don't like about the 'setf' construct is the
unintuitive textual order of the arguments: key, alist, value.
I do like that 'map-put!' puts the arguments in the order I
expect.

If we need to be able to remove an element from an alist
easily, I would want a separate function remove-from-alist.
I personally have not needed such a function.

I have updated the implementation since my old posting.
Here's my current:

(defun add-to-alist (alist-var elt-cons &optional no-replace)
  "Add to the value of ALIST-VAR an element ELT-CONS if it isn't there yet.
If an element with the same car as the car of ELT-CONS is already present,
it is removed unless NO-REPLACE is non-nil, in which case ALIST-VAR is
not changed.  The test for presence of the car of ELT-CONS is done
with `equal'."
  (let ((existing-element (assoc (car elt-cons) (symbol-value alist-var))))
    (if (or (not existing-element) (not no-replace))
        (setf (alist-get (car elt-cons) (symbol-value alist-var))
              (cdr elt-cons)))))