我有以下代码:
(defun TREE-CONTAINS (N TREE)
(cond (( = (car TREE) nil) nil)
(( = (car TREE) N) t)
(t TREE-CONTAINS (N (cdr TREE)))
)
)
,它接受数字N和列表TREE,并检查N是否存在于列表TREE中。非常简单,但是由于某些原因,当我调用函数
时,我总是收到此错误(TREE-CONTAINS 3 '((1 2 3) 7 8))
*** - +: (1 2 3) is not a number
代码有问题吗?我是Lisp的新手,所以也许我只是看不到任何明显的东西..预先感谢!
答案 0 :(得分:9)
语法错误
您的代码包含一些语法错误,这些错误被标记为编译器警告:
CL-USER> (defun TREE-CONTAINS (N TREE)
(cond (( = (car TREE) nil) nil)
(( = (car TREE) N) t)
(t TREE-CONTAINS (N (cdr TREE)))
)
)
;Compiler warnings :
; In TREE-CONTAINS: Undeclared free variable TREE-CONTAINS
; In TREE-CONTAINS: Undefined function N
TREE-CONTAINS
原因是Common Lisp中的括号与其他编程语言的含义不同:它们不用于指定运算符的应用顺序(例如3 * (2 + 4)
中的括号与{{1 }}),但是它们是语法的组成部分,用于指定“语句”的不同部分,例如在3 * 2 + 4
或函数应用程序(例如cond
中)。因此,这种情况下的语法错误出现在最后一行,您应该在其中使用参数(function-name arg1 arg2 ... argn)
和TREE-CONTAINS
调用函数N
,如下所示:
(cdr TREE)
语义错误
但是,如果尝试使用此功能,则会发现错误:
CL-USER> (defun TREE-CONTAINS (N TREE)
(cond (( = (car TREE) nil) nil)
(( = (car TREE) N) t)
(t (TREE-CONTAINS N (cdr TREE)))
)
)
TREE-CONTAINS
原因是您已使用 CL-USER> (TREE-CONTAINS 2 '(1 2 3))
The value NIL is not of the expected type NUMBER.
将数字(=
)与值(car TREE)
进行比较,而nil
仅可用于比较数字。对于一般情况,请使用=
或eq
eql
还有另一个问题:您应该检查列表是否为空,而不是第一个元素为nil。换句话说,第一个条件应该是:
CL-USER> (defun TREE-CONTAINS (N TREE)
(cond (( eql (car TREE) nil) nil)
(( = (car TREE) N) t)
(t (TREE-CONTAINS N (cdr TREE)))
)
)
TREE-CONTAINS
CL-USER> (TREE-CONTAINS 2 '(1 2 3))
T
或更好:
(cond ((eq TREE nil) nil)
样式注释
列表是树的一种特殊情况:如果使用术语树,则程序应该更加复杂,并考虑到元素可以是子列表的情况。
使用小写字母标识符,因为所有内容都转换为大写字母
将右括号放在表达式的末尾,而不是放在新行上。
所以您的功能可能类似于:
(cond ((null TREE) nil)
检查树的成员资格而不是列表
另一方面,如果您要检查通用树,即列表中可以包含子列表,例如(defun list-contains (n list)
(cond ((null list) nil)
((= (car list) n) t)
(t (list-contains n (cdr list)))))
,则在递归中应考虑列表元素的情况本身就是一个列表,然后执行双重递归。这是一个可能的解决方案:
(tree-contains 3 '((1 2 3) 7 8))
答案 1 :(得分:5)
除了可接受的答案外,这是写相同谓词的另一种方式,不带cond
:
(defun list-contains-p (number list)
(and (consp list)
(or (= number (first list))
(list-contains-p number (rest list)))))