这是您的代码,正确缩进:
(DEFINE (pdrome lst)
(cond
((null? lst) #t)
((null? (cdr lst)) #t)
((LIST? (car lst))
((null? (car lst))())
((null? (cdr lst))())
((equal? (caar lst) (caar (reverse lst)))
(pdrome (cdar (reverse(cdar lst))))))
((equal? (car lst) (car(reverse lst)))
(pdrome (cdr (reverse (cdr lst)))))
(else #F)))
请注意第三个子句在应该结束的时候没有结束?或者您可能在检查之前尝试检查几个条件(equal? (caar lst) (caar (reverse lst)))
。
当您调用 时(pdrome '((a b) c (b a)))
,它会到达为真的地步(LIST? (car lst))
,因此它会评估该子句中的其余代码。那是:
((null? (car lst))())
((null? (cdr lst))())
((equal? (caar lst) (caar (reverse lst))
我们来看第一个:((null? (car lst))())
. 如何评估?这是一个包含两个元素的列表,因此请评估第一个元素:(null? (car lst))
. 评估为#F
。然后,我们有(#F ())
. #F
处于功能位置(列表中的第一件事被评估为代码),但不是功能。所以我们得到了错误Object #f is not applicable
。
基本上,cond的每个子句如下所示:
(condition form1 form2 ...)
可以有任意数量的形式,包括零。
所以让我们看看你的单子句
((LIST? (car lst))
((null? (car lst))())
((null? (cdr lst))())
((equal? (caar lst) (caar (reverse lst)))
(pdrome (cdar (reverse(cdar lst))))))
这是条件:
(LIST? (car lst))
这是表格。其中有三个:
((null? (car lst))())
((null? (cdr lst))())
((equal? (caar lst) (caar (reverse lst)))
(pdrome (cdar (reverse(cdar lst))))))
如果条件为真(也就是说,(car lst)
它本身就是一个列表),那么你想做什么?
我将退后一分钟,按照我手动的方式布置算法。
直到我们没有列表了,剪掉第一件事,最后一件,看看第一件和最后一件是不是一样。如果这些东西本身是列表,请反转最后一个。然后继续在列表的中间(即没有第一个或最后一个元素的列表)执行此操作,直到我们最终得到一个空列表或只有一个东西的列表。
现在让我们编写一些代码:
(define (palindrome lst)
(if (null? lst)
#t
(let ((first-element (car lst))
(last-element (car (reverse lst))))
(and (equal? first-element
(if (list? last-element)
(reverse last-element)
last-element))
(palindrome (get-middle lst))))))
(define (get-middle lst)
(if (null? (cdr lst))
'()
(reverse (cdr (reverse (cdr lst))))))
> (palindrome '())
#t
> (palindrome '(a))
#t
> (palindrome '((a)))
#t
> (palindrome '((a) b))
#f
> (palindrome '((a) b (a)))
#t
> (palindrome '((a b) c (b a)))
#t
请注意,此代码与编写的算法略有不同。当它到达一个包含一个元素的列表时(例如,它被称为(palindrome '(a))
,它将获取第一个元素'a
,最后一个元素'a
,确保它们相等,然后调用(get-middle '(a))
,即'()
。然后(palindrome '())
是#f
,所以我们很好。