我正在尝试使用Common Lisp函数编写一个函数,它将计算s表达式中有多少个s表达式。例如:
((x = y)(z = 1)) ;; returns 2
和
((x - y)) ;; returns 1
嵌套表达式是可能的:
((if x then (x = y)(z = w))) ;; returns 3
我编写了一个查找长度的函数,如果没有嵌套表达式,它就可以工作。它是:
(define (length exp)
(cond
((null? exp) 0)
(#t (+ 1 (length (cdr exp))))))
现在我修改了这个,试图将嵌套表达式支持到以下内容:
(define (length exp)
(cond
((null? exp) 0)
((list? (car exp)) (+ 1 (length (cdr exp))))
(#t (length (cdr exp)))))
这适用于没有嵌套的表达式,但总是比嵌套表达式的答案少1。这是因为采用上面的示例((if x then (x = y)(z = w)))
,这将首先查看if
并满足第三个条件,将cdr(表达式的其余部分作为列表)返回到{{1} }。在达到(x = y)之前会发生同样的情况,此时返回length
。这意味着表达式+1
尚未计算在内。
我能以什么方式解释它?添加(if x then .... )
会过度计算未嵌套的表达式。
我需要这个在一个函数中工作,因为嵌套可以在任何地方发生,所以:
+2
答案 0 :(得分:2)
乍一看,你的代码只能向右(cdr-side)而不是向左(car-side)递归,所以这肯定是个问题。
在第二眼看来,这甚至比那更棘手,因为你并不完全是在计算。你需要区分一个缺点开始一个正确的列表与它是一个列表的cdr的情况。如果你要递送到汽车和cdr,那么这些信息就会丢失。我们需要将sexp作为正确的列表进行迭代,
(defun count-proper-list (sexp)
(cond ((atom sexp) 0)
(t (1+ (reduce #'+ (mapcar #'count-proper-list sexp))))))
但是这也将计入顶级列表,因此总是返回比您想要的更多的列表。或许,
(defun count-proper-sublist (sexp)
(1- (count-proper-list sexp)))