I used the last days to dig deeper into clojure.spec in Clojure and ClojureScript.
Until now I find it most useful, to use specs as guards in :pre
This is useful when you don't want to use s/assert
, or can not enable s/check-assserts
. Improving on MicSokoli's answer:
:pre
simply cares that the values returned are all truthy, so we can convert the return value "Success!\n"
to true
(for strictness) and throw
an error with the explanation and the input data in case the output is not successful.
(defn validate [spec input]
(let [explanation (s/explain-str spec input)]
(if (= explanation "Success!\n")
true
(throw (ex-info explanation {:input input}))))
A variation of this could be this one, but it would run the spec twice:
(defn validate [spec input]
(if (s/valid? spec input)
true
(throw (ex-info (s/explain spec input) {:input input}))))
Usage:
(defn person-name [person]
{:pre [(validate ::person person)]}
(str (::first-name person) " " (::last-name person)))