Istota, której szukasz, to kombinator Y *.
Bazując na this page by oleg-at-okmij.org I przeniesiony do y * do 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)))))
Klasycznym przykładem wzajemnego funkcji rekurencyjnej jest parzysta/nieparzysta tak oto przykład:
(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))
))
Można możesz łatwo wysadzić stos za pomocą tych funkcji, jeśli użyjesz wystarczająco dużych argumentów, więc tutaj jest to trampolowana wersja, na przykład kompletność, która w ogóle nie zużywa stosu:
(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 * syntezatora jest bardzo przydatna do określania wzajemnych rekurencyjne definicje monadycznych parserami, z których będę blog wkrótce na lambder.com, zaglądajcie;)
- Lambder
haskell! = Lambda-rachunek – eschulte