2

我正在尝试使用 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(表达式的其余部分作为列表)返回到length. 在达到 (x=y) 之前也是如此,此时+1返回 a。这意味着该表达式(if x then .... )尚未计算在内。

我可以通过哪些方式来解释它?添加+2将过度计算未嵌套的表达式。

我需要它在一个函数中工作,因为嵌套可以在任何地方发生,所以:

((x = y) (if y then (z = w)))
4

1 回答 1

2

乍一看,您的代码只递归到右侧(cdr 侧)而不是左侧(汽车侧),所以这肯定是一个问题。

乍一看,这甚至比这更棘手,因为您并没有准确地计算 conses;您需要区分 cons 开始正确列表的情况与它是列表的 cdr 的情况。如果您要递归到 car 和 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)))
于 2012-11-28T03:54:53.273 回答