Emacs Lisp 中的尾递归展平函数

Tail-recursive flatten function in Emacs Lisp

我正在阅读 Paul Graham 的 On Lisp,并尝试在 Emacs Lisp 中实现这些功能。 其中之一是扁平化:

(flatten '(a (b c) ((d e) f)))
;; Returns:
(a b c d e f)

然而由于某些原因,Paul Graham 给出的实现不适用于 Emacs Lisp(总是 returns nil):

(defun flatten (x)
  (cl-labels ((rec (x acc))
              (cond ((null x) acc)
                    ((atom x) (cons x acc))
                    (t (rec (car x) (rec (cdr x) acc)))))
             (rec x nil)))

(flatten '(1 (3)))
;; Returns:
nil

和ELisp的动态绑定有关系吗?这段代码有什么问题?

正如我在对该问题的评论中所指出的,问题是括号放错了。定义应该是:

(defun flatten (x)
  (cl-labels ((rec (x acc)
                   (cond ((null x) acc)
                         ((atom x) (cons x acc))
                         (t (rec (car x) (rec (cdr x) acc))))))
    (rec x nil)))

在原文中,((rec (x acc))rec定义为返回nil的函数。通过将其更改为 ((rec (x acc)cond 表达式成为 rec 的主体,然后通过在 t 子句后添加右括号再次平衡括号后 condflatten 函数按预期工作:

(flatten '(1 (3)))
(1 3)