LISP-编写函数(REMOVE EL),从列表的所有级别的另一个列表中删除给定的原子或列表

LISP-编写函数(REMOVE EL),从列表的所有级别的另一个列表中删除给定的原子或列表,lisp,common-lisp,Lisp,Common Lisp,我有以下任务: 要构建函数(REMOVE EL),它将从另一个列表中删除给定的原子或列表,这应该应用于列表的每个级别 例如: L=(A B A (B A C X ) X B) (REMOVE A L ) -> (B (B C X) X B) 我编写了以下代码: (defun removeel(el tree) (mapcan (lambda(subtree) (cond ((null subtree) (list nil))

我有以下任务:

要构建函数(REMOVE EL),它将从另一个列表中删除给定的原子或列表,这应该应用于列表的每个级别

例如:

L=(A B A (B A C X ) X B)
(REMOVE A L ) -> (B (B C X) X B)
我编写了以下代码:

(defun removeel(el tree)
  (mapcan (lambda(subtree)
            (cond ((null subtree) (list nil))
                  ((consp subtree) (list (removeel el subtree)))
                  ((eql subtree el) nil)
                  (t (list subtree))))
          tree))
问题是当我移除原子时,它工作得非常好

(removeel 'B' (A B A (B A C X ) X B))
 (A A (A C X) X) 
但是如果我想删除一个列表,它就不起作用了

(removeel '(B A C X) ' (A B A (B A C X ) X B))
  (A B A (B A C X) X B)

应该怎么做才能使它也删除列表?

最简单的方法是引入可选的相等性测试功能,如
删除
标准过程

可以这样看:

(defun rem-rec (item data &key (test #'eql))
  (mapcar (lambda (x) (if (listp x)
                          (rem-rec item x :test test)
                          x))
      (remove item data :test test)))

CL-USER> (rem-rec 1 `(1 2 (3 4 (1 2 3)) (1 (1 2 3) 3 4)))
;;=> (2 (3 4 (2 3)) ((2 3) 3 4))
对于相等列表,您可以使用
equal
(或
equalp
或任何更具体的内容)


但是没有这个测试函数有什么解决办法吗?如果你用“equal”替换代码中的“eq”,它应该对atoms和lists都有效,但是测试函数是常用的标准库习惯用法,它还可以让你执行更复杂的操作,例如删除所有长度为n的列表,或者不管你想做什么,我已经重新安排了一些条件(defun removeel(el-tree)(mapcan(lambda(子树)(cond((null子树)(list-nil))((相等子树el)nil)((consp子树)(list(removeel-subtree)))(t(list-subtree)))并将eql更改为相等。现在一切都好了,谢谢你的帮助;)
CL-USER> (rem-rec '(1 2 3) '(1 2 (3 4 (1 2 3)) (1 (1 2 3) 3 4)) :test #'equal)
;;=> (1 2 (3 4) (1 3 4))