I have an alist in emacs lisp like:
(setq a1
'((:k1 . 1)
(:k2 . 2)
(:k3 . 3)))
and i want to change value of :k1 to 10, like (:k1 . 10)
. How do i do that?
I tried (setf (assoc :k1 a1) '(:k1 . 10))
- it didn't work.
I have an alist in emacs lisp like:
(setq a1
'((:k1 . 1)
(:k2 . 2)
(:k3 . 3)))
and i want to change value of :k1 to 10, like (:k1 . 10)
. How do i do that?
I tried (setf (assoc :k1 a1) '(:k1 . 10))
- it didn't work.
With alists, you usually add a new cons in front of the old one to "shadow" the old value, like so:
(add-to-list 'a1 '(:k1 10))
After you do this (assoc :k1 a1)
will return 10.
If you want to "undo" your change so assoc
again returns your old value, use this code:
(setq a1 (delq (assoc :k1 a1) a1))
This will remove the FIRST match for :k1
from a1
.
As of Emacs 25.1, alist-get
is a place form so you can do:
(setf (alist-get :k1 a1) 10)
The setf
macro doesn't know about assoc
, but you could still use that approach in a slightly more manual fashion:
(let ((item (assoc :k1 a1)))
(setf (car item) :k1)
(setf (cdr item) 10))
and if all that is required is to set the cdr for the given car (rather than replacing both), then we can simplify this to just:
(setf (cdr (assoc :k1 a1)) 10)
This shorter and simpler version works in Emacs Lisp (MAC Lisp) for me:
(setcdr (assoc :k1 a1) 10)
or, if you happen to be using Common Lisp:
(rplacd (assoc :k1 a1) 10)
(Note that setcdr and rplacd may behave slightly different when it comes to which value they return.)
What about assq-delete-all
:
(setq sql-product-alist
(cons '(ms-tsql :server ....)
(assq-delete-all 'ms-tsql sql-product-alist)))
Here's a function based on gavenkoa's suggestion -
(defun alist-set (alist-symbol key value)
"Set KEY to VALUE in alist ALIST-SYMBOL."
(set alist-symbol
(cons (list key value)
(assq-delete-all key (eval alist-symbol)))))
usage -
(let ((foo '((a 1) (b 2))))
(alist-set 'foo 'a 3)
foo) ; => ((a 3) (b 2))