To do runtime coercion, specs need to be walked twice to strip away the branching information: s/conform + s/unform. This introduced extra latency (see the sample below).
New versatile s/walk* to support generic spec walking.
s/valid? allows us to do quickly check if a value conforms to a spec
https://dev.clojure.org/jira/browse/CLJ-2115 could help to return the errors in a single sweep.
for coercion, we do s/conform + s/unform / s/explain
https://dev.clojure.org/jira/browse/CLJ-2116 would separate conforming from specs
Still, when running s/conform + s/unform, we walk the specs twice - which is performance-wise suboptimal. Below is a sample, with Late 2013 MacBook Pro with 2,5 GHz i7, with JVM running as -server.
Despite s/conform is relatively fast, we triple the latency in the sample when running also s/unform. As we know already that we are not interested in the branching info, we could just not emit those.
s/walk* to replace both s/confrom* and s/unform*, maybe even s/explain*. It would take extra mode argument, which would be a Keyword of one of the following:
:validate - return false on first failing spec
:conform - like the current s/conform*, maybe also return s/explain results?
:unform - like the current s/unform*
:coerce - s/conform* + s/unform*, could be optimized (e.g. if no branching info, just return the value)
The public apis could be remain the same (+ optional extra argument with CLJ-2116), and a new s/coerce to call the s/walk* with :coerce.
Single sweep validation & coercion. Happy runtime.