【问题标题】:Elisp - Delete the only item in a list of length 1Elisp - 删除长度为 1 的列表中的唯一项目
【发布时间】:2014-07-06 11:32:37
【问题描述】:

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

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

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

为什么?

如果可以的话,我该怎么做?

【问题讨论】:

    标签: emacs lisp elisp


    【解决方案1】:

    虽然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 单元格的内容。如果应该删除的列表元素是列表中的第一个元素,则删除它的最简单方法是只返回列表的尾部(也称为 cdr)。如果要移除的元素是列表中的only元素,正确的返回值为nil(空列表),没有办法修改一个cons单元格使其变为@ 987654329@.

    您会注意到,如果您删除第二个元素,它确实起作用:

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

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

    【讨论】:

    • 我的第一个例子完全错了。感谢您的详细解释。关于“删除确实使用副作用”,您是在暗示我应该以不同的方式这样做吗?
    • 不,这只是为了解释为什么它有时有效,有时无效。 remove 与 delete 做同样的事情,只是它不使用副作用来修改参数,而是返回删除了相关元素的列表副本,因此如果没有 setq,它将永远无法工作。跨度>
    【解决方案2】:

    来自C-h v delete:

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

    显然'() 的计算结果为nil。

    那么怎么做:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-10-09
      • 2023-03-11
      • 2022-08-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-02-27
      相关资源
      最近更新 更多