Skip to content

Instantly share code, notes, and snippets.

@hiredman
Created December 6, 2016 20:20
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save hiredman/0668d1240e0a623904eca33fed11c45f to your computer and use it in GitHub Desktop.
Save hiredman/0668d1240e0a623904eca33fed11c45f to your computer and use it in GitHub Desktop.
(defn impl-local-keys [spec-map]
(reify
s/Specize
(specize* [s] s)
(specize* [s _] s)
s/Spec
(conform* [_ m]
(reduce
(fn [ret spec-key]
(let [s (get spec-map spec-key)
cv (s/conform s (get ret spec-key))]
(if (s/invalid? cv)
(reduced cv)
(assoc ret spec-key cv))))
m
(keys spec-map)))
(unform* [_ m]
(reduce
(fn [ret spec-key]
(let [s (get spec-map spec-key)
uform (s/unform s (get ret spec-key))]
(assoc ret spec-key uform)))
m
(keys spec-map)))
(explain* [_ path via in x]
(if-not (map? x)
[{:path path :pred 'map? :val x :via via :in in}]
(for [spec-key (keys spec-map)
:let [s (get spec-map spec-key)
datum (get x spec-key)]
exp (s/explain* s (conj path spec-key) via in datum)]
exp)))
(describe* [_]
(list `local-keys
(into {} (for [[k v] spec-map]
[k (s/form v)]))))))
(defmacro local-keys [spec-map]
`(impl-local-keys
~(into {} (for [[k v] spec-map]
[k `(s/spec ~v)]))))
;; user=> (s/explain (local-keys {"foo" int?}) {})
;; val: nil fails at: ["foo"] predicate: int?
;; nil
;; user=> (s/explain (local-keys {"foo" int?}) {"foo" :a})
;; val: :a fails at: ["foo"] predicate: int?
;; nil
;; user=> (s/explain (local-keys {"foo" int?}) {"foo" 1})
;; Success!
;; nil
;; user=>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment