Skip to content

Instantly share code, notes, and snippets.

@ctford
Created May 30, 2014 21:15
Show Gist options
  • Save ctford/fe2282c04482b23bde26 to your computer and use it in GitHub Desktop.
Save ctford/fe2282c04482b23bde26 to your computer and use it in GitHub Desktop.
An alternative implementation of map that won't silently return nils for missing keys.
(ns strict-map.map)
(deftype StrictMap [inner]
clojure.lang.IPersistentMap
(assoc [this k v]
(StrictMap. (.assoc inner k v)))
(assocEx [this k v]
(StrictMap. (.assocEx inner k v)))
(without [this k]
(StrictMap. (.without inner k)))
java.lang.Iterable
(iterator [this]
(.iterator inner))
clojure.lang.Associative
(containsKey [this k]
(.containsKey inner k))
(entryAt [this k]
(.entryAt inner k))
clojure.lang.IPersistentCollection
(count [this]
(.count inner))
(cons [this x]
(StrictMap. (.cons inner x)))
(empty [this]
(.empty inner))
(equiv [this other]
(and (map? other) (= (seq other) (seq inner))))
clojure.lang.Seqable
(seq [this]
(.seq inner))
clojure.lang.IFn
(invoke [this k]
(.invoke inner k))
(invoke [this k default]
(.invoke inner k default))
(applyTo [this args]
(.applyTo inner args))
clojure.lang.ILookup
(valAt [this k]
(let [v (get inner k)]
(cond (not (contains? inner k))
(throw (new Exception (str "Key '" k "' not found in strict map '" inner "'.")))
(map? v)
(StrictMap. v)
:otherwise
v)))
(valAt [this k default]
(let [v (get inner k)]
(cond (not (contains? inner k))
default
(map? v)
(StrictMap. v)
:otherwise
v))))
(defn strict
"Convert an ordinary map into one that throws an Exception if an unknown key is requested."
[m] (StrictMap. m))
@ctford
Copy link
Author

ctford commented Jun 2, 2014

You mean invoke?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment