La creatura che stai cercando è combinatore Y *.
Sulla base this page by oleg-at-okmij.org ho portato il Y * a 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)))))
Il classico esempio di funzione ricorsiva mutuo è pari/dispari: ecco l'esempio:
(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))
))
Puoi facilmente saltare lo stack con queste funzioni se si usano argomenti abbastanza grandi, quindi ecco la versione trampolino di esso per esempio la completezza che non consuma affatto:
(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))
))
Il Y * Combinator è molto utile per la definizione di definizioni ricorsive reciproci di parser monadici, di cui sarò sul blog presto su lambder.com, restate sintonizzati;)
- Lambder
haskell! = Lambda-calcolo – eschulte