Lisp Стиль вопрос метки локальные функции или нет?

Мне было интересно, существует ли стандартная практика использования меток в Lisp. Я возился с реализацией Lisp алгоритма, описанного в первом ответе здесь ленивно создавая перестановки В моей текущей версии используются метки, чтобы разбить части функциональности.

(defun next-permutation (pmute)
  (declare (vector pmute))
  (let ((len (length pmute)))
    (if (> len 2)
        (labels ((get-pivot ()
                   (do ((pivot (1- len) (1- pivot)))
                       ((or (= pivot 0)
                            (< (aref pmute (1- pivot))
                               (aref pmute pivot)))
                        pivot)))
                 (get-swap (pivot)
                   (let ((swp (1- len)))
                     (loop for i from (1- len) downto pivot do
                           (if (or (and (> (aref pmute i)
                                           (aref pmute (1- pivot)))
                                        (< (aref pmute i) (aref pmute swp)))
                                   (< (aref pmute swp) (aref pmute (1- pivot))))
                               (setf swp i)))
                     swp))
                 (next (swp pivot)
                   (rotatef (aref pmute (1- pivot)) (aref pmute swp))
                   (reverse-vector pmute pivot (1- len))))
          (let ((piv (get-pivot)))
            (if (> piv 0)
                (next (get-swap piv) piv)
              nil))))))

Так как каждая метка называется только один раз, мне было интересно, считается ли это плохой практикой, поскольку единственная причина для этого в этом случае - по эстетическим соображениям. Я бы сказал, что текущая версия с ярлыками более ясна, но это может противоречить общей мудрости, о которой я не знаю, новичок в Lisp.

Ответ 1

Нет, все в порядке. Запись названных функций делает код немного более самодокументированным и более модульным.

Иногда я бы также перечислял все переменные, используемые в функциях arglist, и не использовал переменные из закрывающей функции. Это делает интерфейс немного понятнее и помогает перемещать функцию в коде (при необходимости).

Локальные функции также позволяют добавлять локальные строки документации и описания интерфейсов.

Если локальные функции становятся слишком большими, и они также могут использоваться снаружи, я бы извлек их и сделав их глобальными.

Ответ 2

Я не вижу в этом ничего плохого. Вы делаете эти два подпроцесса очень ясными и легкими для куска, что позволяет легко понять, что функция действительно делает, просто глядя на тело. Также его теперь легко продвигать внутренние функции в глобальные функции, если вам нужно.

Ответ 3

Не будучи чем-то другим, кроме новичка Lisp, я бы сказал, что вы поступаете правильно: сделать ваш код более читаемым, называя куски.