Существо, которого вы ищете, является Y * Комбинатор.
Основываясь на this page by 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, следите за обновлениями;)
- Lambder
haskell! = Лямбда-исчисление – eschulte