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
子句后添加右括号再次平衡括号后 cond
,flatten
函数按预期工作:
(flatten '(1 (3)))
(1 3)
我正在阅读 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
子句后添加右括号再次平衡括号后 cond
,flatten
函数按预期工作:
(flatten '(1 (3)))
(1 3)