I\'m trying to write a function that returns a memoized recursive function in Clojure, but I\'m having trouble making the recursive function see its own memoized bindings. I
There is an interesting way to do it that does rely neither on rebinding nor the behavior of def
. The main trick is to go around the limitations of recursion by passing a function as an argument to itself:
(defn make-fibo [y]
(let
[fib
(fn [mem-fib x]
(let [fib (fn [a] (mem-fib mem-fib a))]
(if (<= x 2)
y
(+ (fib (- x 1)) (fib (- x 2))))))
mem-fib (memoize fib)]
(partial mem-fib mem-fib)))
Then:
> ((make-fibo 1) 50)
12586269025
What happens here:
fib
recursive function got a new argument mem-fib
. This will be the memoized version of fib
itself, once it gets defined.fib
body is wrapped in a let
form that redefines calls to fib
so that they pass the mem-fib
down to next levels of recursion.mem-fib
is defined as memoized fib
partial
as the first argument to itself to start the above mechanism.This trick is similar to the one used by the Y combinator to calculate function's fix point in absence of a built-in recursion mechanism.
Given that def
"sees" the symbol being defined, there is little practical reason to go this way, except maybe for creating anonymous in-place recursive memoized functions.