问题描述
我正在尝试通过Common Lisp:符号计算的温和介绍这本书来学习 Common Lisp。此外,我正在使用 SBCL、Emacs 和 Slime。
在第 8 章中,作者介绍了递归的概念。更具体地说,他展示了树上的 cad/cdr 递归。关于此主题的练习之一是如何展平嵌套列表:
奇怪的事情出现在答题纸中,显示这是正确答案:
本书的答题纸解决方案没有在我的环境下通过问题提供的示例产生预期的结果。
(defun flatten-book (tree)
(cond ((atom tree) (list tree))
(t (append (flatten-book (car tree))
(flatten-book (cdr tree))))))
它充满了 NIL
而它不应该如此。因此,我开始了我的 REPL:
CL-USER> (flatten-book '((A B (R)) A C (A D ((A (B)) R) A)))
(A B R NIL NIL A C A D A B NIL NIL R NIL A NIL NIL)
为了获得预期的结果,我需要更改插入 null clause
的方法:
(defun my-flatten (tree)
(cond ((null tree) nil)
((atom tree) (list tree))
(t (append (my-flatten (car tree))
(my-flatten (cdr tree))))))
这将返回正确答案:
CL-USER> (my-flatten '((A B (R)) A C (A D ((A (B)) R) A)))
(A B R A C A D A B R A)
到目前为止,我很喜欢这本书。它似乎是 Common Lispers 中的经典之作。
这是书的答卷中的错误吗?我错过了什么?或许是历史的变化?也许与不同的编译器有关?
解决方法
书错了。
然而,通过这个小小的改变,书中的答案再次奏效:
(defun flatten (tree)
(cond ((null tree) tree) ;; this case was forgotten by the book!
((atom tree) (list tree))
(t (append (flatten (car tree))
(flatten (cdr tree))))))