Actually, the code I posted might behave less well if the timing is less uniform. It's better to store wait times with queue entries rather than with cache entries:
(defn my-memoize "Returns a memoized version of a referentially transparent function. The memoized version of the function keeps a cache of the mapping from arguments to results and, when calls with the same arguments are repeated often, has higher performance at the expense of higher memory use. Cached results are removed from the cache when their time to live value expires." [function time-to-live] (let [cached-results (ref {}) last-time (ref (System/currentTimeMillis)) expiry-queue (ref []) process-queue #(when-not (empty? @expiry-queue) (Thread/sleep (:wait (first @expiry-queue))) (dosync (let [args (:item (first (ensure expiry-queue))) item (get (ensure cached-results) args) t (- (:time item) 100)] (if (<= t (System/currentTimeMillis)) (alter cached-results dissoc args)) (ref-set expiry-queue (vec (rest @expiry-queue))))) (recur)) ts-agent (agent nil)] (fn [& args] (let [result (if-let [r (get @cached-results args)] (:result r) (apply function args))] (dosync (let [t (+ time-to-live (System/currentTimeMillis)) l (max (ensure last-time) (System/currentTimeMillis)) w (- t l) q (ensure expiry-queue)] (alter cached-results assoc args {:result result :time t}) (ref-set last-time t) (alter expiry-queue conj {:item args :wait w}) (if (empty? q) (send ts-agent (fn [_] (.start (Thread. process-queue))))))) result)))) This version also drops the println. user=> (def x (my-memoize #(do (println %) (+ % 10)) 1000)) #'user/x user=> (doall (for [n [1 2 4 1 2 3 1 2 3 2 3 2 3 2 3 1 4]] (do (Thread/sleep 300) (x n)))) 1 2 4 ; pause 3 ; long pause 1 4 (11 12 14 11 12 13 11 12 13 12 13 12 13 12 13 11 14) --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~----------~----~----~----~------~----~------~--~---