atom-backed-lru-cache
Clojure
(defn lru-cache
"Returns {:get f :put f} for a cache that evicts the least recently used key."
[capacity]
(let [state (atom {:order [] :data {}})
touch (fn [{:keys [order data]} k]
(let [order (conj (vec (remove #{k} order)) k)]
(if (> (count order) capacity)
(let [old (first order)]
{:order (vec (rest order)) :data (dissoc data old)})
{:order order :data data})))]
{:get (fn [k]
(let [v (get-in @state [:data k])]
(when (some? v) (swap! state touch k))
v))
:put (fn [k v]
(swap! state (fn [s] (assoc-in (touch s k) [:data k] v)))
v)}))