Хвост-рекурсивная функция уплощения в Emacs Lisp - PullRequest
1 голос
/ 23 июня 2019

Я изучаю Пола Грэма на 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 Ответ

1 голос
/ 24 июня 2019

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

(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)
...