Fork me on GitHub

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.

Alex Miller (Clojure team)18:02:04

you could just do something like (s/cat :route-id ::route-id :params (s/* any))

Alex Miller (Clojure team)18:02:26

but it depends a lot what route-params is

Alex Miller (Clojure team)18:02:39

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

Alex Miller (Clojure team)21:02:20

(s/keys*) would automatically handle all registered specs for the tail of that


i want default case to fail

Alex Miller (Clojure team)21:02:01

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

Alex Miller (Clojure team)21:02:45

I don't understand enough what you're doing

Alex Miller (Clojure team)21:02:49

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 example


can I do :default ::s/invalid ?

Alex Miller (Clojure team)22:02:20

oh, you mean multi-method default


(defmethod tagmm :default [_] ::s/invalid) 
will test that out

Alex Miller (Clojure team)22:02:42

the multimethod returns specs so you need to return a spec that always fails

Alex Miller (Clojure team)22:02:19

so probably more (constantly false) would work


that seems more canonical


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