Хвост-рекурсивная функция уплощения в Emacs Lisp

Я изучаю On Lisp Пола Грэма и пытаюсь реализовать функции в Emacs Lisp. Один из них сглажен:

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

Однако по какой-то причине реализация, данная Полом Грэмом, не работает на 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 ответ

Решение

Как отмечается в моем комментарии к вопросу, проблема заключается в неуместных скобках. Определение должно быть:

(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)
Другие вопросы по тегам