Skip to content

Instantly share code, notes, and snippets.

@mfikes
Last active February 27, 2018 20:54
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 mfikes/1c0bdeb1ec1c54902605e2692bbcef5c to your computer and use it in GitHub Desktop.
Save mfikes/1c0bdeb1ec1c54902605e2692bbcef5c to your computer and use it in GitHub Desktop.
Spec for value or deref

Let's say we have a map, like {::age 36} that we can validate with

(s/def ::age number?)
(s/def ::my-map (s/keys :req [::age]))

Now, let's say that we have a function that can take either a valid value, or something that can be derefd to obtain a valid value.

Here is a predicate that derefable values will satisfy:

 (defn deref? [x]
   #?(:clj  (instance? clojure.lang.IDeref x) 
      :cljs (satisfies? IDeref x)))

We can write a spec-producing function that produces the kind of spec we want:

(defn value-or-deref [spec] 
  (s/or :value spec 
        :deref (s/and deref? #(s/valid? spec (deref %)))))

Let's try it out

 (s/valid? (value-or-deref ::my-map) {::age 36}) ; true
(s/valid? (value-or-deref ::my-map) {::age "foo"}) ; false
(s/valid? (value-or-deref ::my-map) (atom {::age 36})) ;true
(s/valid? (value-or-deref ::my-map) (atom {::age "foo"})) ; false
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment