How do I generate memoized recursive functions in Clojure?

前端 未结 8 976
[愿得一人]
[愿得一人] 2020-12-25 11:31

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

相关标签:
8条回答
  • 2020-12-25 12:26

    Here's a cross between the Y-combinator and Clojure's memoize:

    (defn Y-mem [f]
      (let [mem (atom {})]
        (#(% %)
         (fn [x]
           (f #(if-let [e (find @mem %&)]
                (val e)
                (let [ret (apply (x x) %&)]
                  (swap! mem assoc %& ret)
                  ret))))))))
    

    You can macrosugar this up:

    (defmacro defrecfn [name args & body]
      `(def ~name
           (Y-mem (fn [foo#]
                     (fn ~args (let [~name foo#] ~@body))))))
    

    Now for using it:

    (defrecfn fib [n]
      (if (<= n 1)
          n
          (+' (fib (- n 1))
              (fib (- n 2)))))
    
    user=> (time (fib 200))
    "Elapsed time: 0.839868 msecs"
    280571172992510140037611932413038677189525N
    

    Or the Levenshtein distance:

    (defrecfn edit-dist [s1 s2]
      (cond (empty? s1) (count s2)
            (empty? s2) (count s1)
            :else (min (inc (edit-dist s1 (butlast s2)))
                       (inc (edit-dist (butlast s1) s2))
                       ((if (= (last s1) (last s2)) identity inc)
                          (edit-dist (butlast s1) (butlast s2))))))
    
    0 讨论(0)
  • 2020-12-25 12:27

    Here is the simplest solution:

    (def fibo
      (memoize (fn [n]
                 (if (< n 2)
                   n
                   (+ (fibo (dec n))
                      (fibo (dec (dec n))))))))
    
    0 讨论(0)
提交回复
热议问题