Ответ 1
Существо, которое вы ищете, это комбинатор Y *.
Основываясь на этой странице oleg-at-okmij.org Я портировал Y * на Clojure
(defn Y* [& fs]
(map (fn [f] (f))
((fn [x] (x x))
(fn [p]
(map
(fn [f]
(fn []
(apply f
(map
(fn [ff]
(fn [& y] (apply (ff) y)))
(p p)))))
fs)))))
Классический пример взаимной рекурсивной функции четный/нечетный, вот пример:
(let
[[even? odd?]
(Y*
(fn [e o]
(fn [n]
(or (= 0 n) (o (dec n)))))
(fn [e o]
(fn [n]
(and (not= 0 n) (e (dec n)))))
)
]
(do
(assert (even? 14))
(assert (odd? 333))
))
Вы можете легко взорвать стек с помощью этих функций, если используете достаточно большие аргументы, так что здесь есть бамбуковая версия, например, полнота, которая вообще не потребляет стек:
(let
[[even? odd?]
(Y*
(fn [e o]
(fn [n]
(or (= 0 n) #(o (dec n)))))
(fn [e o]
(fn [n]
(and (not= 0 n) #(e (dec n)))))
)
]
(do
(assert (trampoline even? 144444))
(assert (trampoline odd? 333333))
))
Комбинатор Y * очень полезен для определения взаимно-рекурсивных определений монадических парсеров, из которых я буду вести блог на lambder.com, следите за обновлениями;)
- Ламбер