Общая функция для самостоятельного вызова рекурсивной функции в определении - PullRequest
4 голосов
/ 17 мая 2011

Есть ли в Clojure макрос или основная функция считывателя, которая похожа на recur, но возможна с нехвостовой позицией?

Например, в этой рекурсивной функции

(defn insertR* [newkey oldkey l]
  (cond
    (empty? l)  '()
    (not (seq? (first l)))
        (if (= (first l) oldkey)
        (cons oldkey (cons newkey (insertR* newkey oldkey (rest l))))
        (cons (first l) (insertR* newkey oldkey (rest l))))    
    :else
        (cons (insertR* newkey oldkey (first l)) (insertR* newkey oldkey (rest l)))))

Есть ли какая-то универсальная функция, которую я могу использовать для вызова самой себя вместо явного вызова insertR*?

Ответы [ 2 ]

3 голосов
/ 17 мая 2011

Ваш вопрос неясен. Если вы имеете в виду: Могу ли я сделать это без использования стека? Нет. Ваш insertR* имеет несколько самостоятельных вызовов, и это невозможно выразить без стека.

Если вы имеете в виду: могу ли я использовать такое слово, как recur, чтобы означать «называть себя рекурсивно», и мне все равно, использует ли оно стек? На самом деле, нет. Вы могли бы написать это самостоятельно, хотя. Что-то вроде:

(defmacro defrec [name & fntail]
  `(def ~name (fn ~'recurse ~@fntail)))

(defrec foo [x]
  (when-not (zero? x)
    (recurse (dec x))))

Я подозреваю, что у этого есть несколько отверстий, но это в основном то, что вы думаете.

0 голосов
/ 17 мая 2011

Зачем вам нужна эта функция / макрос?recur создан для оптимизации хвостового вызова.Кажется, ваша функция не позволяет этого (может быть, я ошибаюсь).Хотя ты сказал, что тебе это не нужно.Почему вы хотите явно заменить вызывающий insertR * на что-то другое?Если вам не нравится каждый раз передавать newkey oldkey (и они не меняются), вы можете создать внутреннюю функцию, которая будет использовать эти клавиши.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...