Lisp S表达式和列表长度/大小

时间:2012-11-28 01:05:09

标签: list lisp common-lisp s-expression

我正在尝试使用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

1 个答案:

答案 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)))