我正在尝试评估列表中的每个原子,看看它是否等于提供的数字,如果没有则删除,但我遇到了一个小问题。
我写了以下代码:
(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就可以了。
答案 0 :(得分:2)
car
和cdr
是cons
类型对象的访问者。由于t
和"hello"
不是cons
,因此您会收到错误消息。
要修复它,您需要知道函数返回的类型而不是car
,除非您知道它是cons
修改强>
首先关闭ident并清理代码..嵌套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
或{{1}所以在这种情况下长度为0时返回nil
。
我添加了默认情况,其中前两个谓词都不是真实的,并且默认返回t
。
我根据使用的功能命名了它。 nil
只能用于数字参数,因此永远不会对符号,字符串等起作用。如果您追求的是相同的值,则需要使用=
。
现在看看这个我们可以看到函数返回值不是很容易推理。我们知道equal
,t
和nil
或list
尾部的任何部分都是可能的,因此list
可能不起作用,或者car
它可能不会产生数字。
更好的方法是:
(car nil)
nil
具有相同的数值,然后递归列表的其余部分(跳过元素)number
列表中包含第一个元素,并将结果与列表的其余部分一起递归。代码看起来像这样:
cons
答案 1 :(得分:1)
您可以采取一些措施来改善此功能。
首先,让我们正确缩进
(defun equal1 (V L)
(cond
((= (length L) 0))
(T (cond
((not (= V (car (equal1 V (cdr L))))) (cdr L))))))
您可以使用(= (length l) 0)
,而不是(zerop (length l))
。一个小的音节点。更糟糕的是,该分支没有返回任何价值。如果列表L
为空,我们应该返回什么?
该功能的问题出在第一个T
的{{1}}分支中。
我们想做的是
cond
V
的项目保留为=
该函数应返回一个列表。
表达式
V
试图(我认为)处理条件1和2.但是它显然不起作用。
我们必须记住,项目在列表中,同等功能的结果需要是一个列表。在上面的表达式中,函数的结果将是一个布尔值,因此函数调用的结果将是布尔值。
该函数需要沿着列表的每个元素步进,当它看到匹配的值时,跳过它,否则使用cons函数来构建过滤的输出列表。
这是一个帮助你的骨架。请注意,我们不需要嵌入式(cond
((not (= V (car (equal1 V (cdr L))))) (cdr L)))
,只需处理3个条件 - 列表为空,过滤掉值,或继续构建列表。
cond
当然,这是Common Lisp,有一个内置函数可以做到这一点。您可以查看(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
...