hmm…
I’m wanting to spec some data that is coming from a 3rd party library, the Ataraxy router.
It always uses the namespaced keyword :ataraxy/result
to contain the parsed parameters for the route; however because ataraxy is configured on a route by route basis; the exact data structure differs, yet the ring request map always contains the same namespaced keyword.
It strikes me that this is an unfortunate mistake; in that the same global keyword is being used to name different data.
What is the best way to spec such a thing?
I’m thinking a multispec is really the only option, that could dispatch on the first
argument. :ataraxy/result
is a vector of the form [:route/id ,,,route-params,,,]
or I suppose I could coerce it into something else first 😞
actually thinking it’s better to just spec the functions after it, that don’t depend on the :ataraxy/result
key.
you could just do something like (s/cat :route-id ::route-id :params (s/* any))
but it depends a lot what route-params is
if it's kwargs, then keys* would work great
my data looks like {::type "foobar" ::a ... ::b ... ::c ...} I want different s/keys validation based on the value of ::type whats the feature i'm looking for
it's like ~ conditional spec validation polymorphic to field value
i guess some sort of mulitmethod on the spec
reading about multi-spec now, this looks like it
for the :default case
what would be a canonical way to fail spec validation
defmethod tagmm :default
(s/keys*) would automatically handle all registered specs for the tail of that
i want default case to fail
validation
you can definitely use multi-spec for this if that makes sense
what is a canonical way to implement :default
besides a conformer that always throws exceptions
I don't understand enough what you're doing
what does :default mean?
(s/def ::tag #{:a :b :c :d})
(s/def ::example-key keyword?)
(s/def ::different-key keyword?)
(defmulti tagmm :tag)
(defmethod tagmm :a [_] (s/keys :req-un [::tag ::example-key]))
(defmethod tagmm :default [_] (s/keys :req-un [::tag ::different-key]))
(s/def ::example (s/multi-spec tagmm :tag))
(gen/sample (s/gen ::example))
here's the examplecan I do :default ::s/invalid ?
oh, you mean multi-method default
(defmethod tagmm :default [_] ::s/invalid)
will test that outthe multimethod returns specs so you need to return a spec that always fails
so probably more (constantly false) would work
ok great
or #{}
that seems more canonical
a set of no values :)
particular in the spec explanations
it'd be nice to get something that made sense
a q out of curiosity more than anything else:
(spec/valid? (spec/coll-of char? :min-count 1 :max-count 20) "abc")
doesn't work (and a straightforward impl would underperform anyway?)
are there spec-related libraries offering a coll-of
-like API that efficiently works on strings?
I just like coll-of
's API, in that it doesn't resemble regex