Good points! Testing array-map briefly led me to believe they can be
used as the clojure equivalent of Java\s LinkedHashMaps.

Here's a version that uses a vector to remember order of insertion - I
guess I have to use refs and transactions now:

(defn bounded-memoize
  [f bound]
  (let [mem (ref {})
        v (ref [])]
    (fn [& args]
      (if-let [e (find @mem args)]
        (val e)
        (let [ret (apply f args)]
          (dosync
           (when (= (count @v) bound)
             (alter mem dissoc (first @v))
             (alter v subvec 1))
           (alter mem assoc args ret)
           (alter v conj args))
          ret)))))

Haven't looked at clojure's queues yet, they might make the code more
concise, but by looking at that other post, they don't seem to be
exposed in a clojurey way (using a java class name).

On Mar 9, 11:22 am, Michał Marczyk <michal.marc...@gmail.com> wrote:
> On 8 March 2010 05:31, Eugen Dück <eu...@dueck.org> wrote:
>
> > And here's a variant that evicts elements when the size of the cache
> > exceeds some limit. In that case, the first item that was put in it
> > will be dissoc'ed. I'm using an array-map to accomplish this:
>
> I don't think this will work as you expect it to. There are two reasons:
>
> (1) Array maps are transparently converted to hash maps when they grow
> beyond a certain size:
>
> user> (class (array-map :a 1 :b 2 :c 3 :d 4 :e 5 :f 6 :g 7 :h 8))
> clojure.lang.PersistentArrayMap
> user> (class (assoc (array-map :a 1 :b 2 :c 3 :d 4 :e 5 :f 6 :g 7 :h 8) :i 9))
> clojure.lang.PersistentArrayMap
> user> (class (assoc (array-map :a 1 :b 2 :c 3 :d 4 :e 5 :f 6 :g 7 :h
> 8) :i 9 :j 10))
> clojure.lang.PersistentHashMap
>
> (2) More importantly, if you dissoc the first key from an array map,
> then assoc a new key onto the array map, the newly assoc key will take
> the first slot:
>
> user> (first (assoc (dissoc (array-map :a 1 :b 2 :c 3) :a) :d 4))
> [:d 4]
>
> I'd suggest a vector instead; they're countable in constant time and
> you can use, say, conj and rest for add to end of queue / eject from
> front of queue.
>
> The idea is certainly a good one, though, so with the above mentioned
> issues fixed, this will be a nice utility function. Thanks for
> sharing!
>
> Sincerely,
> Michał

-- 
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

Reply via email to