在Emacs Lisp中,我似乎无法从列表中删除最后一项。
;; This works.
(setq list1 '(alpha beta))
(delete 'alpha list1) ;; => (beta)
;; list1 => (beta)
;; NOPE.
(setq list1 '(alpha))
(delete 'alpha list1) ;; => nil
;; list1 => (alpha)
为什么?
如果有可能,我该怎么做?
答案 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))