There's no requirement that association lists have unique keys, as your example shows, nor is there any particular reason to expect them to have unique keys -- at base, it's just a list of lists with no restrictions on the car
s of the nested lists.
I believe it's idiomatic to exploit the fact that there are no restrictions on the keys to override initial key/value pairs by pushing a new pair onto the front of the list. Some of the core functionality for alists works implicitly along these lines. Here, for example, is the docstring for assoc
:
Return non-nil if KEY is `equal' to the car of an element of LIST.
The value is actually the first element of LIST whose car equals KEY.
Hence, it returns only the first element, regardless of how many other elements come later in the list with the same key. That can be a pretty useful feature.
Update. If you really want to prevent add-to-list
from shadowing a prior key/value pair (although you're kind of fighting the language in doing so), you can define the following function and pass it to the compare-fn
parameter in add-to-list
(note that it does zero error-checking):
(defun key-used-p (elt1 elt2)
"Helper function for add-to-list: returns non-nil if key is
already in use in an association list."
(eq (car elt1) (car elt2)))
(setq alist '((a . 1) (b . 1) (c . 1))) ; original list
(add-to-list 'alist '(a . 2) nil #'key-used-p) ; adds nothing because a in use
(add-to-list 'alist '(d . 2) nil #'key-used-p) ; adds (d . 2)
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…