Emacs Lisp中的尾递归展平函数

时间:2019-06-23 11:59:25

标签: elisp on-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上不起作用(总是返回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的动态绑定有关吗?此代码有什么问题?

1 个答案:

答案 0 :(得分:1)

正如我在对问题的评论中指出的那样,问题是括号放错了位置。定义应为:

(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子句之后添加右括号来再次平衡括号1}},cond函数将按预期工作:

flatten