Заменить элемент в списке объединений в elisp
У меня есть alist в emacs lisp как:
(setq a1
'((:k1 . 1)
(:k2 . 2)
(:k3 . 3)))
и я хочу изменить значение: от k1 до 10, например (:k1 . 10)
. Как это сделать?
Я пробовал (setf (assoc :k1 a1) '(:k1 . 10))
- он не работал.
Ответы
Ответ 1
С помощью alists вы обычно добавляете новые минусы перед старым, чтобы "затенять" старое значение, например:
(add-to-list 'a1 '(:k1 10))
После этого (assoc :k1 a1)
вернет 10.
Если вы хотите "отменить" свое изменение, поэтому assoc
снова возвращает ваше старое значение, используйте этот код:
(setq a1 (delq (assoc :k1 a1) a1))
Это приведет к удалению соответствия FIRST для :k1
из a1
.
Ответ 2
Макрос setf
не знает о assoc
, но вы можете использовать этот подход несколько более вручную:
(let ((item (assoc :k1 a1)))
(setf (car item) :k1)
(setf (cdr item) 10))
и если все, что требуется, - установить cdr для данного автомобиля (вместо замены обоих), тогда мы можем упростить это:
(setf (cdr (assoc :k1 a1)) 10)
Ответ 3
Начиная с Emacs 25.1, alist-get
- это форма места, которую вы можете сделать:
(setf (alist-get :k1 a1) 10)
Ответ 4
Как насчет assq-delete-all
:
(setq sql-product-alist
(cons '(ms-tsql :server ....)
(assq-delete-all 'ms-tsql sql-product-alist)))
Ответ 5
Здесь функция, основанная на предположении гавенько -
(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)))))
использование -
(let ((foo '((a 1) (b 2))))
(alist-set 'foo 'a 3)
foo) ; => ((a 3) (b 2))