Skip to content

Instantly share code, notes, and snippets.

@ctford
Created May 30, 2014 21:15
Show Gist options
  • Select an option

  • Save ctford/fe2282c04482b23bde26 to your computer and use it in GitHub Desktop.

Select an option

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))
@ericnormand
Copy link
Copy Markdown

Thinking it should wrap the .inner call with a new StrictMap.

@ctford
Copy link
Copy Markdown
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