Elisp - 删除长度为1的列表中的唯一项目

时间:2014-07-06 11:32:38

标签: emacs lisp elisp

在Emacs Lisp中,我似乎无法从列表中删除最后一项。

;; This works.
(setq list1 '(alpha beta))
(delete 'alpha list1) ;; => (beta)
;; list1 => (beta)

;; NOPE.
(setq list1 '(alpha))
(delete 'alpha list1) ;; => nil
;; list1 => (alpha)

为什么?

如果有可能,我该怎么做?

2 个答案:

答案 0 :(得分:7)

虽然delete确实使用副作用来删除列表元素,但不保证这样做。使用它的正确方法是将结果分配回变量:

(setq list1 (delete 'alpha list1))

事实上,当我尝试你的第一个例子时,list1也保持不变:

ELISP> (setq list1 '(alpha beta))
(alpha beta)
ELISP> (delete 'alpha list1)
(beta)
ELISP> list1
(alpha beta)

这是因为delete是一个函数,而不是宏或特殊形式。这意味着它不能改变变量list1的绑定;它只能改变list1指向的cons单元格的内容。如果应该删除的列表元素是列表中的第一个元素,则删除它的最简单方法是返回列表的尾部(a.k.a.cdr)。如果要删除的元素是列表中的 only 元素,则正确的返回值为nil(空列表),并且无法修改cons单元格以使其成为成为nil

如果删除第二个元素,您会注意到它

ELISP> (setq list1 '(alpha beta))
(alpha beta)
ELISP> (delete 'beta list1)
(alpha)
ELISP> list1
(alpha)

在这种情况下,delete最终会执行(setcdr list1 nil),只需要更改cons单元格,而不是list1的绑定。

答案 1 :(得分:5)

来自C-h v delete

  

(setq foo (delete element foo))' to be sure of correctly changing the value of a sequence foo'。

显然'()评估为nil

如何做到:

(setq list1 '(alpha))
(setq list1 (delete 'alpha list1))