lisp elisp associative-array

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)