31

我在 emacs lisp 中有一个 alist,例如:

(setq a1
 '((:k1 . 1)
   (:k2 . 2)
   (:k3 . 3)))

我想将:k1 的值更改为 10,例如(:k1 . 10)。我怎么做?

我试过(setf (assoc :k1 a1) '(:k1 . 10))了 - 它没有用。

4

6 回答 6

22

使用 alists,您通常会在旧的 cons 前面添加一个新的 cons 以“遮蔽”旧值,如下所示:

(add-to-list 'a1 '(:k1 10))

执行此操作(assoc :k1 a1)后将返回 10。

如果您想“撤消”您的更改以便assoc再次返回您的旧值,请使用以下代码:

(setq a1 (delq (assoc :k1 a1) a1))

这将删除 from 的第一个匹配项。:k1a1

于 2012-04-08T13:55:05.900 回答
14

从 Emacs 25.1 开始,alist-get它是一个地方表单,因此您可以执行以下操作:

(setf (alist-get :k1 a1) 10)
于 2016-11-26T05:44:47.207 回答
6

setf宏不知道,assoc但您仍然可以以稍微手动的方式使用该方法:

(let ((item (assoc :k1 a1)))
  (setf (car item) :k1)
  (setf (cdr item) 10))

如果只需要为给定汽车设置 cdr(而不是同时替换两者),那么我们可以将其简化为:

(setf (cdr (assoc :k1 a1)) 10)
于 2012-04-08T14:54:40.597 回答
5

这个更短更简单的版本适用于我的 Emacs Lisp (MAC Lisp):

(setcdr (assoc :k1 a1) 10)

或者,如果您碰巧使用的是 Common Lisp:

(rplacd (assoc :k1 a1) 10)

(请注意,当涉及到返回的值时,setcdr 和 rplacd 的行为可能略有不同。)

于 2018-04-14T06:20:57.160 回答
1

怎么样assq-delete-all

(setq sql-product-alist
      (cons '(ms-tsql :server ....)
            (assq-delete-all 'ms-tsql sql-product-alist)))
于 2015-04-10T12:31:23.673 回答
1

这是基于 givenkoa 建议的功能-

(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))
于 2015-12-11T22:36:51.027 回答