You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Common Lisp中delete-if与搭配setf的remove-if行为差异大的原因是什么

Common Lisp 中 delete-if 未修改原列表的原因说明

核心原理

Common Lisp 标准明确规定:delete-if 这类破坏性序列操作,仅允许实现复用原序列的内存空间构造过滤后的结果,不保证会修改原变量的绑定指向。你遇到的表现完全符合规范,是对破坏性操作的常见理解误区。

具体问题分析

你的测试代码中需要删除的(cons 1 2)正好是列表*c1*的头元素:

  • 列表本质是单向链表,头节点被删除时,不可能通过修改原链表的节点内容来改变原变量的指向,只能返回新的头节点作为操作结果
  • 你没有将delete-if的返回值赋值给*c1*,所以*c1*的绑定始终指向原列表的头节点,打印结果自然和操作前一致

正确用法

破坏性序列操作的返回值必须赋值给原变量才能保证符合预期,和remove-if的用法完全一致:

;; 正确的 delete-if 写法
(setf *c1* (delete-if
 (lambda (x)
   (progn
     (format t "trying to compare ~A ~A~%" x (equal x (cons 1 2)))
     (equal x (cons 1 2))))
 *c1*))

补充注意事项

  • 所有Common Lisp的破坏性序列操作(包括delete、nreverse、nconc等)都需要将返回值赋值回原变量,不能依赖操作自动修改原绑定
  • 即使删除的不是头元素,不同实现的破坏性操作行为也可能存在差异,只有拿返回值赋值才能保证跨实现的兼容性

内容的提问来源于stack exchange,提问作者ruby_object

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.06 02:42:01