Common lisp LISP不能乘T的车

Common lisp LISP不能乘T的车,common-lisp,Common Lisp,我试图计算列表中的每个原子,看看它是否等于提供的数字,如果不等于,则删除它,但我遇到了一个小问题 我编写了以下代码: (defun equal1(V L) (cond((= (length L) 0)) (T (cond( (not(= V (car(equal1 V (cdr L))))) (cdr L) ))) ) ) (equal1 5 '(1 2 3 4 5)) 我得到以下错误 Error: Cannot take CAR of T. 如果我

我试图计算列表中的每个原子,看看它是否等于提供的数字,如果不等于,则删除它,但我遇到了一个小问题

我编写了以下代码:

(defun equal1(V L)
     (cond((= (length L) 0))
          (T (cond( (not(= V (car(equal1 V (cdr L))))) (cdr L) )))
     )
)

(equal1 5 '(1 2 3 4 5))
我得到以下错误

Error: Cannot take CAR of T.
如果我为操作添加(写“hello”),如果为true,则会得到以下错误:

Error: Cannot take CAR of "hello".

我对LISP还是一个新手,我想知道到底发生了什么,我该如何解决这个问题,这样我就可以正确地评估每个原子,如果没有,就删除它,从而删除动作的cdr L。

car
cdr
cons
类型对象的访问器。由于
t
“hello”
不是
cons
,因此会收到一条错误消息

要修复它,您需要知道函数返回的是什么类型,而不是
car
,除非您知道它是
cons

编辑

首先识别并清除代码。。嵌套的
cond
不成功,因为默认情况下
cond
是if-elseif-else结构:

(defun remove-number (number list)
  (cond ((= (length list) 0) 
         t)
        ((not (= number (car (remove-number number (cdr list))))) 
         (cdr list))))
        (t 
         nil)))
我想让您注意到,我添加了一个默认行为,即返回
t
,当我们知道
=
返回
t
nil
时,当长度为0时,它返回
t

我添加了一个默认情况,其中前面的两个谓词都不是真的,它默认返回
nil

我根据使用的函数给它命名
=
只能用于数字参数,因此这对符号、字符串等不起作用。如果要查找相同的值,则需要使用
equal

现在看看这个,我们可以看到函数返回值不是很容易推理的。我们知道
t
nil
list
list
尾部的任何部分都是可能的,因此执行
car
可能不起作用,或者在
(car nil)
的情况下,它可能不会产生一个数字

更好的方法是:

  • 检查列表是否为空,然后返回
    nil
  • 检查第一个元素是否与
    number
    具有相同的数值,然后与列表的其余部分一起递归(跳过该元素)
  • 默认情况下,应使用
    cons
    列表中的第一个元素和递归结果以及列表的其余部分
  • 代码如下所示:

    (defun remove-number (number list)
      (cond ((endp list) '())
            ((= (car list) number) (remove-number ...))
            (t (cons ...))))
    

    car
    cdr
    cons
    类型对象的访问器。由于
    t
    “hello”
    不是
    cons
    ,因此会收到一条错误消息

    要修复它,您需要知道函数返回的是什么类型,而不是
    car
    ,除非您知道它是
    cons

    编辑

    首先识别并清除代码。。嵌套的
    cond
    不成功,因为默认情况下
    cond
    是if-elseif-else结构:

    (defun remove-number (number list)
      (cond ((= (length list) 0) 
             t)
            ((not (= number (car (remove-number number (cdr list))))) 
             (cdr list))))
            (t 
             nil)))
    
    我想让您注意到,我添加了一个默认行为,即返回
    t
    ,当我们知道
    =
    返回
    t
    nil
    时,当长度为0时,它返回
    t

    我添加了一个默认情况,其中前面的两个谓词都不是真的,它默认返回
    nil

    我根据使用的函数给它命名
    =
    只能用于数字参数,因此这对符号、字符串等不起作用。如果要查找相同的值,则需要使用
    equal

    现在看看这个,我们可以看到函数返回值不是很容易推理的。我们知道
    t
    nil
    list
    list
    尾部的任何部分都是可能的,因此执行
    car
    可能不起作用,或者在
    (car nil)
    的情况下,它可能不会产生一个数字

    更好的方法是:

  • 检查列表是否为空,然后返回
    nil
  • 检查第一个元素是否与
    number
    具有相同的数值,然后与列表的其余部分一起递归(跳过该元素)
  • 默认情况下,应使用
    cons
    列表中的第一个元素和递归结果以及列表的其余部分
  • 代码如下所示:

    (defun remove-number (number list)
      (cond ((endp list) '())
            ((= (car list) number) (remove-number ...))
            (t (cons ...))))
    

    您可以做一些事情来改进此功能

    首先,让我们适当地缩进它

    (defun equal1 (V L)
      (cond
        ((= (length L) 0))
        (T (cond
             ((not (= V (car (equal1 V (cdr L))))) (cdr L))))))
    
    不要说
    (=(长度l)0)
    ,您可以使用
    (zerop(长度l))
    。次要的三段论观点。更糟糕的是,分支不返回任何值。如果列表
    L
    为空,我们应该返回什么

    函数的问题出现在第一个
    cond
    T
    分支中

    我们想做的是

  • 删除与
    V
  • 将任何不是
    =
    的项目保留到
    V
  • 函数应该返回一个列表

    表情

    (cond 
      ((not (= V (car (equal1 V (cdr L))))) (cdr L)))
    
    他(我认为)正在尝试处理条件1和条件2。然而,它显然不起作用

    我们必须记住,项目在一个列表中,相等函数的结果需要是一个列表。在上面的表达式中,函数的结果将是布尔值,因此函数调用的结果将是布尔值

    该函数需要沿着列表中的每个元素单步执行,当它看到匹配的值时,跳过它,否则使用cons函数构建过滤后的输出列表

    这里有一个骨架来帮助你。请注意,我们不需要嵌入的
    cond
    ,只需要处理3个条件-list empty、过滤一个值或继续构建列表

    (defun equal-2 (v l)
      (cond
        ((zerop (length L))  nil)
        ((= v (car l))  <something goes here>)      ;skip or filter the value
        (t (cons (car l) <something goes here>)))) ;build the output list
    
    (定义等于-2(v l)
    (续)
    ((零p(长度L))零)
    (=v(car l));跳过或过滤该值
    (t(cons(car l));;建立输出