Common lisp GISC练习8.24和8.26:如果cond结果表中的条件未按预期工作

Common lisp GISC练习8.24和8.26:如果cond结果表中的条件未按预期工作,common-lisp,Common Lisp,David Touretzky的《符号计算状态温和介绍》练习8.24和8.26: 8.24:写倒计时,一种使用考虑递归的列表从n开始倒计时的函数。计数5应生成列表5 4 3 2 1 8.26:假设我们想要修改倒计时,以便列表可以 构造以零结尾。例如,倒计时5将产生543200。[……] 因此,我尝试将这两个练习组合成一个函数倒计时,该函数采用包含零的关键字参数,如下所示: (defun countdown (n &key (incl-zero nil)) (cond ((ze

David Touretzky的《符号计算状态温和介绍》练习8.24和8.26:

8.24:写倒计时,一种使用考虑递归的列表从n开始倒计时的函数。计数5应生成列表5 4 3 2 1

8.26:假设我们想要修改倒计时,以便列表可以 构造以零结尾。例如,倒计时5将产生543200。[……]

因此,我尝试将这两个练习组合成一个函数倒计时,该函数采用包含零的关键字参数,如下所示:

(defun countdown (n &key (incl-zero nil))
  (cond
    ((zerop n) (if incl-zero '(0) nil))
    (t (cons n (countdown (1- n))))))

(countdown 5)
(countdown 5 :incl-zero t)
但是,两个倒计时调用都返回54321,因此看起来:inclzero t没有达到if条件。为什么会这样?

天哪,我觉得自己很愚蠢

(defun countdown (n &key (incl-zero nil))
  (cond
    ((zerop n) (if incl-zero '(0) nil))
    (t (cons n (countdown (1- n) :incl-zero incl-zero)))))

(countdown 5)
(countdown 5 :incl-zero t)
我想我成了递归迷因的牺牲品..

天哪,我觉得自己很愚蠢

(defun countdown (n &key (incl-zero nil))
  (cond
    ((zerop n) (if incl-zero '(0) nil))
    (t (cons n (countdown (1- n) :incl-zero incl-zero)))))

(countdown 5)
(countdown 5 :incl-zero t)

我猜是递归迷因的牺牲品。

您注意到了错误,但请注意,当您的参数从一个调用变为另一个调用时,您可能应该定义一个局部递归函数,只传递确实发生变化的参数。这更容易书写和理解。此外,传递关键字参数可能会带来一点运行时开销

(defun countdown (n &key (incl-zero nil))
  (labels ((recurse (n)
             (cond
               ((zerop n) (if incl-zero '(0) nil))
               (t (cons n (recurse (1- n)))))))
    (recurse n)))

您注意到了错误,但请注意,当您的参数在一个调用到另一个调用时没有变化时,您可能应该定义一个局部递归函数,以便只传递变化的参数。这更容易书写和理解。此外,传递关键字参数可能会带来一点运行时开销

(defun countdown (n &key (incl-zero nil))
  (labels ((recurse (n)
             (cond
               ((zerop n) (if incl-zero '(0) nil))
               (t (cons n (recurse (1- n)))))))
    (recurse n)))