(defcache LUCache [cache lu limit]
CacheProtocol
(lookup [_ item]
(get cache item))
(lookup [_ item not-found]
(get cache item not-found))
(has? [_ item]
(contains? cache item))
(hit [_ item]
(LUCache. cache (update-in lu [item] inc) limit))
(miss [_ item result]
(if (>= (count lu) limit) ;; need to evict?
(let [min-key (if (contains? lu item)
::nope
(first (peek lu))) ;; maybe evict case
c (-> cache (dissoc min-key) (assoc item result))
l (-> lu (dissoc min-key) (update-in [item] (fnil inc 0)))]
(LUCache. c l limit))
(LUCache. (assoc cache item result) ;; no change case
(assoc lu item 0)
limit)))
(evict [this key]
(if (contains? this key)
(LUCache. (dissoc cache key)
(dissoc lu key)
limit)
this))
(seed [_ base]
(LUCache. base
(build-leastness-queue base limit 0)
limit))
Object
(toString [_]
(str cache \, \space lu \, \space limit)))