Reemplazar elemento en la lista de asociaciones en elisp
associative-array (6)
Tengo una alistada en emacs lisp como:
(setq a1
''((:k1 . 1)
(:k2 . 2)
(:k3 . 3)))
y quiero cambiar el valor de: k1 a 10, como (:k1 . 10)
. ¿Cómo puedo hacer eso?
Intenté (setf (assoc :k1 a1) ''(:k1 . 10))
- no funcionó.
¿Qué pasa con assq-delete-all
?
(setq sql-product-alist
(cons ''(ms-tsql :server ....)
(assq-delete-all ''ms-tsql sql-product-alist)))
A partir de Emacs 25.1, alist-get
es una forma de lugar que puede hacer:
(setf (alist-get :k1 a1) 10)
Aquí hay una función basada en la sugerencia de gavenkoa:
(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)))))
uso
(let ((foo ''((a 1) (b 2))))
(alist-set ''foo ''a 3)
foo) ; => ((a 3) (b 2))
Con las alistas, por lo general, agrega una nueva contras frente a la anterior para "sombrear" el valor antiguo, de esta manera:
(add-to-list ''a1 ''(:k1 10))
Después de hacer esto (assoc :k1 a1)
devolverá 10.
Si desea "deshacer" su cambio para que assoc
devuelva nuevamente su valor anterior, use este código:
(setq a1 (delq (assoc :k1 a1) a1))
Esto eliminará la primera coincidencia para :k1
de a1
.
Esta versión más corta y simple funciona en Emacs Lisp (MAC Lisp) para mí:
(setcdr (assoc :k1 a1) 10)
O, si estás usando Common Lisp:
(rplacd (assoc :k1 a1) 10)
(Tenga en cuenta que setcdr y rplacd pueden comportarse ligeramente diferente cuando se trata del valor que devuelven).
La macro setf
no conoce assoc
, pero aún podría utilizar ese enfoque de una manera un poco más manual:
(let ((item (assoc :k1 a1)))
(setf (car item) :k1)
(setf (cdr item) 10))
y si todo lo que se requiere es configurar el cdr para el auto dado (en lugar de reemplazar ambos), entonces podemos simplificar esto simplemente a:
(setf (cdr (assoc :k1 a1)) 10)