Error handling 如何在不使用LISP中的remove函数的情况下从列表中删除元素

Error handling 如何在不使用LISP中的remove函数的情况下从列表中删除元素,error-handling,lisp,Error Handling,Lisp,我试图编写一个函数来从列表中删除一个元素,但我得到一个错误,即“应该是lambada函数”,我不知道我的代码是正确的还是错误的。您的代码有问题 您的代码有一些问题。首先,让我们看一下标准缩进 (defun my_remove(e list1 list2) (if (null list1) nil ((setf x car(list1)) (if (!= x e) ((my_append e list2 ) (setf y cdr(list1))

我试图编写一个函数来从列表中删除一个元素,但我得到一个错误,即“应该是lambada函数”,我不知道我的代码是正确的还是错误的。

您的代码有问题 您的代码有一些问题。首先,让我们看一下标准缩进

  (defun my_remove(e list1 list2)
  (if (null list1)
   nil
  ((setf x car(list1))
    (if (!= x e)
    ((my_append  e list2 )
    (setf y cdr(list1))
    (my_remove(e y list2)))

    ((setf y cdr(list1))
    (my_remove(e y list2))
     )))))
每个标记行都有一个问题。Lisp中函数调用的语法为

(defun my_remove(e list1 list2)
  (if (null list1)
      nil
      ((setf x car(list1))                   ; (i)
       (if (!= x e)
           ((my_append  e list2 )            ; (ii)
            (setf y cdr(list1))              ; (iii)
            (my_remove(e y list2)))          ; (iv)
           ((setf y cdr(list1))              ; (v)
            (my_remove(e y list2)))))))      ; (vi)
这意味着在您的
(i)
行中,您试图调用一个名为
(setf x car(list1))
的函数,该函数带有一个参数
(if(!=xe)
)。当然,这不是函数的名称,我怀疑即使它是,您也不想用参数
(if(!=xe)…
调用它。同样地

(function argument…)
正在尝试将
x
设置为变量
car
的值(并且没有),然后将新值分配给位置
(列表1)
。由于函数调用的语法是
(函数参数…
),因此您需要:

(setf x car (list1))

如果您试图对窗体进行排序,您可以考虑使用,在其中可以提供多个表单,或者<代码> PRONN/<代码>(参见)。 例如,而不是

(setf x (car list1))
你可能想要

           ((my_append  e list2 )            ; (ii)
            (setf y cdr(list1))              ; (iii)
            (my_remove(e y list2)))          ; (iv)
不过,你也会遇到一些问题。在
(iii)
(iv)
中,您需要使用
(cdr list 1)
(my_remove e y list 2)
,如上所述,但您也有一个问题,即您正在评估
(ii)
(iii)
,但您正在丢弃该值

简化方法 我认为如果您考虑一下
my remove
的简单定义,可能会对您有利。通常,列表是空列表
()
或cons单元格,其car是列表的第一个元素,其cdr是列表的其余部分。您可以使用这样的定义,然后:

  • 删除(x,列表)
    • 若列表是空的,那个么返回列表(它是空的,所以它肯定不包含x)
    • 如果列表不是空的,则
      • 如果列表的第一个元素是x,则返回remove(x,rest(list))
      • 否则,列表的第一个元素不是x,因此返回一个新列表,其第一个元素是列表的第一个元素,其余元素是remove(x,rest(list))
在代码中,这看起来像:

           (progn
            (my_append  e list2 )            ; (ii)
            (setf y cdr(list1))              ; (iii)
            (my_remove(e y list2)))          ; (iv)
那些嵌套的
if
s看起来有点难看,您可能希望在此处使用
cond
,即使您不需要它允许的多个表达式体:

CL-USER> (my-remove 1 '(1 2 3 1 2 3))
(2 3 2 3)
由于没有主体的
cond
子句(其测试表单的计算结果为true)返回测试表单的值,因此您甚至可以将最后一个子句简化一点:

(defun my-remove (element list)
  (cond
    ((endp list)
     list)
    ((eql element (first list))
     (my-remove element (rest list)))
    (t
     (list* (first list) (my-remove element (rest list))))))

正确的格式将有很大帮助(这不是一个尖刻的评论;很难仅从parens来区分语法缩进问题!)我是这里的初学者,我不知道正确的缩进,我尝试了我在上面写的任何东西。如果你能使用一个支持Lisp的编辑器,例如Emacs或内置在IDE中的编辑器,它将对你有很大帮助(例如,Lispworks的编辑).vim也了解Lisp语法。你是从课堂上还是从教科书上学习的?代码中有一些非常基本的语法问题。几个Lisp示例函数可以清楚地说明这一点。我认为你应该离线整理其中的一些,然后再做一次尝试。对不起,实际上我正在尝试设置“x”中的“list1”What is list*and What is endp?@user39495在这里它可以被
cons
替换,但是
list*
类似于
list
,除了最后一个参数是结果列表的尾部。例如
(list*12'(34 5));=>(1 2 3 4 5)
endp
null
的同义词@user39495 Sylwester的答案是正确的。我喜欢使用
endp
/
首先
/
/
/
列表*
来强调我们在这里使用的是列表,而不是
cons
单元格的树。不过,这些问题很容易用快速的Goo来回答gle搜索,或者更具体地说,lispdoc.com上的搜索,例如。
list*
,搜索起来有点困难,但它与。
(defun my-remove (element list)
  (cond
    ((endp list)
     list)
    ((eql element (first list))
     (my-remove element (rest list)))
    (t
     (list* (first list) (my-remove element (rest list))))))
(defun my-remove (element list)
  (cond
    ((endp list) list)
    ((eql element (first list)) (my-remove element (rest list)))
    ((list* (first list) (my-remove element (rest list))))))