Another option that has been added since the guide was written is s/assert
which seems closer to what you're suggesting.
(defn name [user]
{:pre [(s/assert :common/user user)]}
(-> user :user/name))
;; need to enable assertion checking - this can also be enabled globally
with system property clojure.spec.check-asserts
(s/check-asserts true)
(name {:user/name "Elon"})
"Elon"
(name {:x "Elon"})
ExceptionInfo Spec assertion failed
val: {:x "Elon"} fails predicate: (contains? % :user/name)
:clojure.spec/failure :assertion-failed
clojure.core/ex-info (core.clj:4725)
Rather than use it in a precondition, you can also use s/assert directly in
the code.
On Wednesday, September 14, 2016 at 7:37:24 AM UTC-5,
[email protected] wrote:
>
> (ns spec-test.core
> (:require [clojure.spec :as s]))
>
> (s/def :user/name string?)
> (s/def :common/user (s/keys :req [:user/name]))
>
> ; first version of name (using :pre)
> (defn name [user]
> {:pre [(s/valid? :common/user user)]}
> (-> user :user/name))
>
> ; This statement works ok and returns "Elon":
> (name {:user/name "Elon"})
>
> ; but this statement...
> (name {:x "Elon"})
>
> ;...will throw:
> CompilerException java.lang.AssertionError:
> Assert failed: (s/valid? :common/user user)
>
> ; ...but then I don't get as much information
> ; about the error as if I would have called:
> (s/explain :common/user {:x "Elon"})
>
> ;...which also contains the predicate:
> val: {:x "Elon"} fails spec: :common/user
> predicate: (contains? % :user/name)
>
> ; (second version of name - more verbose)
> ; or do I need to wite it like this:
> (defn name [user]
> (let [parsed (s/conform :common/user user)]
> (if (= parsed ::s/invalid)
> (throw (ex-info "Invalid input" (s/explain-data :common/user user)))
> (-> user :user/name))))
>
> ; so that:
> (name {:x "Elon"})
>
> ; ...will return:
> CompilerException clojure.lang.ExceptionInfo:
> Invalid input #:clojure.spec{:problems}
> ({:path [], :pred (contains? % :user/name),
> :val {:x "Elon"}, :via [:common/user], :in []})
>
> ; It should be nice if I could be able to write it like this
> ; (or similar, to get a better error message):
> (defn name [user]
> {:pre [(s/explain :common/user user)]}
> (-> user :user/name))
>
>
--
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to [email protected]
Note that posts from new members are moderated - please be patient with your
first post.
To unsubscribe from this group, send email to
[email protected]
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
---
You received this message because you are subscribed to the Google Groups
"Clojure" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
For more options, visit https://groups.google.com/d/optout.