exoscale / coax

Clojure.spec coercion library for clj(s)
Other
118 stars 4 forks source link

refactor to enable symbol & form overrides #2

Closed mpenet closed 4 years ago

mpenet commented 4 years ago

This migrates the code away from a global multimethod to a single registry. We can now override anything (namespaced kw, predicate, spec form).

Previously we could only override namespaced keys, which made difficult to say "I want specs composed of string? to coerce that way", we had to register string? via a spec like so first (s/def ::string string?) and then override ::string. Now we can just say ex:

(sc/coerce ... x {::sc/ident {`string? parse-long}))

real world case of bertrand with vector?:

(sc/coerce vector? x {::sc/ident {`vector? parse-coma-separated-string}))
;; or 
(s/def ::thing (s/map-of ::foo vector?))

(sc/coerce ::thing x {::sc/ident {`vector? parse-coma-separated-string})) ; composite

extract from the tests:

    (is (= 1 (sc/coerce `string? "1" {::sc/ident {`string? p/parse-long}}))
        "overrides works on qualified-idents")

    (is (= [1] (sc/coerce `(s/coll-of string?) ["1"]
                          {::sc/ident {`string? p/parse-long}}))
        "overrides works on qualified-idents, also with composites")

we can now also pass ::sc/override-form and override s/coll-of & co or any of the new symbolic specs forms that will come with spec2.

This breaks backward compat by changing the option keys:

::overrides becomes ::ident ::form and ::enum, they all are overrides but act differently, ::ident is used for qualified-idents type of specs (keywords, predicates), ::form for composites, so it's a generator of coercer since they take parameters, and ::enum allows to override the enum set coercer potentially.