In clojure, I would like to write a tail-recursive function that memoizes its intermediate results for subsequent calls.
[EDIT: this question has been rewritten using gcd
as an example instead of factorial
.]
The memoized gcd
(greatest common divisor) could be implemented like this:
(def gcd (memoize (fn [a b]
(if (zero? b)
a
(recur b (mod a b))))
In this implementation, intermediate results are not memoized for subsequent calls. For example, in order to calculate gcd(9,6)
, gcd(6,3)
is called as an intermediate result. However, gcd(6,3)
is not stored in the cache of the memoized function because the recursion point of recur
is the anonymous function that is not memoized.
Therefore, if after having called gcd(9,6)
, we call gcd(6,3)
we won't benefit from the memoization.
The only solution I can think about will be to use mundane recursion (explicitely call gcd
instead of recur
) but then we will not benefit from Tail Call Optimization.
Bottom Line
Is there a way to achieve both:
- Tail call optimization
- Memoization of intermediate results for subsequent calls
Remarks
- This question is similar to Combine memoization and tail-recursion. But all the answers there are related to
F#
. Here, I am looking for an answer inclojure
. - This question has been left as an exercise for the reader by The Joy of Clojure (chap 12.4). You can consult the relevant page of the book at http://bit.ly/HkQrio.