从lisp(elisp)中的关联列表中弹出元素

时间:2010-08-13 11:18:16

标签: emacs lisp elisp

我正在寻找一种方法从关联列表中“弹出”一个元素,换句话说就是“破坏性”的关联:

(setq alist '((a . 1) (b . 2))
(assoc-pop 'a alist) ;; -> (a . 1)
;; alist -> ((b . 2))

elisp线束中是否有任何功能? 获得symilar功能最优雅的方法是什么? (不确定这种“副作用”是一种很好的做法,即使有可能!)

2 个答案:

答案 0 :(得分:3)

我没有注意到这样的内置运算符,但我认为你可以很快得到这个功能:

(defmacro assoc-pop (key alist)
  `(let ((result (assoc ,key ,alist)))
     (setq ,alist (delete result ,alist))
     result))

答案 1 :(得分:1)

assq-delete-all接近你想要的。它按对象标识(eq)查找元素,而不是按值相等(equal)查找元素。它删除所有匹配的元素,而不仅仅是第一个。它返回修改后的列表。您可以调整此函数的代码以执行您想要的操作。 (但如果您要在循环中拨打assoc-pop,并且所有密钥都是符号,那么assq-delete-all可以满足您的所有要求。)

请注意"a"'a是完全不同的对象:第一个是字符串,第二个是符号。所以你的第二行应该是(assoc-pop 'a alist)

但实际上,调用(assoc-pop 'a alist)无效(除非assoc-pop是宏),因为它无法删除列表中的第一个元素。您可以创建一个以符号作为参数的函数,并根据add-to-list的模型修改符号值的列表。您可以将其称为(assoc-pop 'a 'alist)