We're updating the issue view to help you get more done. 

[spec] Generic spec walking for clojure.spec

Description

Problem

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).

Proposal

New versatile s/walk* to support generic spec walking.

Current status

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.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 (require '[clojure.spec.alpha :as s]) (s/def ::id int?) (s/def ::name string?) (s/def ::languages (s/coll-of #{:clj :cljs} :into #{})) (s/def ::street string?) (s/def ::zip string?) (s/def ::number int?) (s/def ::address (s/keys :req-un [::street ::zip ::number])) (s/def ::user (s/keys :req [::id] :req-un [::name ::address] :opt-un [::languages])) (def value {::id 1 :name "Liisa" :languages #{:clj :cljs} :address {:street "Hämeenkatu" :number 24 :zip "33200"}}) ; 2.0 µs (cc/quick-bench (s/conform ::user value)) ; 6.2 µs (cc/quick-bench (s/unform ::user (s/conform ::user value)))

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.

Suggestion

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.

Results

Single sweep validation & coercion. Happy runtime.

Environment

[org.clojure/spec.alpha "0.1.134"]

Status

Assignee

Unassigned

Reporter

Tommi Tommi

Labels

None

Approval

None

Patch

None

Affects versions

Release 1.9

Priority

Major