Lisp 从嵌套列表中删除

Lisp 从嵌套列表中删除,lisp,common-lisp,Lisp,Common Lisp,我有一个作业把我难住了!我必须创建一个函数goo(ALL),它将删除L中的每个a,并且它还必须处理嵌套列表 这是我到目前为止得到的 (defun goo(A L) (cond ((null L) nil) ; if list is null, return nil (T ; else list is not null (cond ((atom (car L))) ;if car L is an atom ((cond ((equal A (car L)) (goo A

我有一个作业把我难住了!我必须创建一个函数goo(ALL),它将删除L中的每个a,并且它还必须处理嵌套列表

这是我到目前为止得到的

(defun goo(A L)
(cond ((null L) nil) ; if list is null, return nil
(T  ; else list is not null
    (cond ((atom (car L))) ;if car L is an atom
        ((cond ((equal A (car L)) (goo A (cdr L)))  ;if car L = A, call goo A cdr L
            (T (cons (car L) (goo A (cdr L)))))) ;if car L != A, 
    (T (cons (goo A (car L)) (goo A (cdr L))))))    ;else car L is not atom, call goo on car L and call goo on cdr L
))

不管我给它什么,这个函数都返回True。

你的父母都搞砸了。将最后一个参数在
(atom(car L))
周围移动,以包含下一个
cond
表达式。我建议使用显示匹配参数的IDE

至于造型,如果你不知道。这样,您就不需要再次使用
t
cond
。如果您只测试一个谓词,并且仅基于该谓词做出决策,那么您也可以这样做

注意:这最初是由最初的提问者在中作为问题的编辑发布的

我尝试了另一种方法,它现在起作用了

(defun goo(A L)
(cond ((null L) nil)
      ((atom (car L)) (cond ((equal A (car L)) (goo A (cdr L)))
                        (T (cons (car L) (goo A (cdr L))))))
      (T (cons (goo A (car L)) (goo A (cdr L))))
))
注2:常规格式应如下所示,以显示程序结构:


我认为这可能更容易被视为一个替代树木的问题。定义一个函数很容易,它采用一棵树并替换其中满足测试要求的子树。有一个标准函数可以做到这一点,但它用相同的东西替换每个匹配的子树。如果我们将元素替换为从子树计算的值,则对我们更有用:

(defun %subst-if (new test tree)
  "Replace subtrees of TREE that satisfy TEST with the result 
of calling NEW with the subtree."
  (cond
    ;; If tree satifies the test, return (new tree).
    ((funcall test tree)
     (funcall new tree))
    ;; If tree is a cons, recurse.
    ((consp tree)
     (cons (%subst-if new test (car tree))
           (%subst-if new test (cdr tree))))
    ;; Otherwise, just return the leaf.
    (tree)))
有了它,就可以很容易地定义我们需要的函数类型。当一个元素X出现在嵌套列表结构中的某个位置时,这意味着有一个cons单元的car是X。我们希望用它的cdr替换该cons单元,但也要在该单元的cdr上递归。这并不难:

(defun replace* (x list &key (test 'eql))
  "Remove occurrences of X in LIST and  its sublists."
  (%subst-if
   (lambda (cons)
     "Replace elements of the form (X . more) with
      (replace* x more :test test)."
     (replace* x (cdr cons) :test test))
   (lambda (subtree)
     "Detect subtrees of the form (X . more)."
     (and (consp subtree)
          (funcall test x (car subtree))))
   list))


谢谢你,伙计。移动参数给了我一个错误,但我尝试了另一种使用cond multiple子句的方法,并使其起作用。如果您找到了适合您的解决方案,请不要将其编辑到问题中,而是将其作为答案发布,并将其标记为已接受。目前,我已将其复制到社区维基答案中,并将其从问题中删除。尽管如此,请随意发布您自己的答案,我将删除CW答案。
(defun replace* (x list &key (test 'eql))
  "Remove occurrences of X in LIST and  its sublists."
  (%subst-if
   (lambda (cons)
     "Replace elements of the form (X . more) with
      (replace* x more :test test)."
     (replace* x (cdr cons) :test test))
   (lambda (subtree)
     "Detect subtrees of the form (X . more)."
     (and (consp subtree)
          (funcall test x (car subtree))))
   list))
(replace* 'a '(1 a (2 a 3) a 4 a 5))
;=> (1 (2 3) 4 5)