У меня есть список в emacs lisp, например:
(setq a1
'((:k1 . 1)
(:k2 . 2)
(:k3 . 3)))
и я хочу изменить значение: k1 на 10, например (:k1 . 10)
. Как мне это сделать?
Пробовал (setf (assoc :k1 a1) '(:k1 . 10))
- не помогло.
У меня есть список в emacs lisp, например:
(setq a1
'((:k1 . 1)
(:k2 . 2)
(:k3 . 3)))
и я хочу изменить значение: k1 на 10, например (:k1 . 10)
. Как мне это сделать?
Пробовал (setf (assoc :k1 a1) '(:k1 . 10))
- не помогло.
В списках вы обычно добавляете новый минус перед старым, чтобы «затенить» старое значение, например так:
(add-to-list 'a1 '(:k1 10))
После этого (assoc :k1 a1)
вернет 10.
Если вы хотите «отменить» свое изменение, чтобы assoc
снова вернуло ваше старое значение, используйте этот код:
(setq a1 (delq (assoc :k1 a1) a1))
Это удалит ПЕРВОЕ соответствие для :k1
из a1
.
Начиная с Emacs 25.1, alist-get
является формой места, поэтому вы можете:
(setf (alist-get :k1 a1) 10)
Макрос setf
ничего не знает о assoc
, но вы все равно можете использовать этот подход чуть более ручным способом:
(let ((item (assoc :k1 a1)))
(setf (car item) :k1)
(setf (cdr item) 10))
и если все, что требуется, это установить cdr для данного автомобиля (а не заменить оба), то мы можем упростить это до простого:
(setf (cdr (assoc :k1 a1)) 10)
Эта более короткая и простая версия у меня работает в Emacs Lisp (MAC Lisp):
(setcdr (assoc :k1 a1) 10)
или, если вы используете Common Lisp:
(rplacd (assoc :k1 a1) 10)
(Обратите внимание, что setcdr и rplacd могут вести себя немного по-разному, когда речь заходит о том, какое значение они возвращают.)
А как насчет assq-delete-all
:
(setq sql-product-alist
(cons '(ms-tsql :server ....)
(assq-delete-all 'ms-tsql sql-product-alist)))
Вот функция, основанная на предложении гавенкоа -
(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))