Skip to content

Instantly share code, notes, and snippets.

@kriyative
Created May 9, 2012 07:03
Show Gist options
  • Save kriyative/2642569 to your computer and use it in GitHub Desktop.
Save kriyative/2642569 to your computer and use it in GitHub Desktop.
Extending Clojure Map with `deftype` and `defprotocol`
(ns extmap
(:import
[clojure.lang ILookup Associative]))
;; ----------------------------------------------------------------
;; TrackableMap is a persistent map which keeps track of the number of
;; times `get` was called on it.
(defprotocol Trackable
(getStats [self]))
(deftype TrackableMap [data stats]
ILookup
(valAt [this key]
(swap! stats inc)
(get @data key))
Associative
(assoc [this key val]
(swap! data assoc key val)
this)
Trackable
(getStats [this] @stats))
(defn make-trackable-map [& [init-map]]
(TrackableMap. (atom (or init-map {})) (atom 0)))
(let [m (assoc (make-trackable-map {:foo 1}) :bar 2)]
[(get m :foo) (get m :foo) (get m :bar) (getStats m)])
;; => [1 1 2 3]
;; ----------------------------------------------------------------
;; RandomValueMap is a persistent map which creates new associations
;; for keys which miss, with random integer values
(deftype RandomValueMap [data]
ILookup
(valAt [this key]
(or (get @data key)
(let [val (Math/round (* (Math/random) 100))]
(swap! data assoc key val)
val)))
Associative
(assoc [this key val]
(swap! data assoc key val)
this))
(defn make-random-value-map [& [init-map]]
(RandomValueMap. (atom (or init-map {}))))
(let [m (assoc (make-random-value-map {:foo 1}) :baz 2)]
[(get m :foo)
(get m :bar) ; create new assoc
(get m :bar) ; return the assoc created above
(get m :baz)])
;; => [1 38 38 2]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment