Fork me on GitHub

Hello all! A question, let's say I have:

(s/def ::event-common (s/keys :req [::nonce ::payload]))
I would like to declare an event that has fixed ::type:
(s/def ::command-event (s/merge ::event-common -- what do I put here? --))


(I was also wondering if I can use s/and with my ::event-common def)

Alex Miller (Clojure team)03:09:42

@richiardiandrea not entirely clear what you want to do. maybe: (s/def ::command-event (s/merge ::event-common (s/keys :req [::type]))) ?

Alex Miller (Clojure team)04:09:29

or are you asking because they can’t both be satisfied that way? I suspect this is the kind of thing where you’re happier using s/multi-spec


@alexmiller tnx for answering, I have a multi-spec in place so that I can check if the event conforms to my expected :types. Re-reading my question I see that maybe I am looking at it from the wrong angle..I will clarify my own ideas first and ask again


I think I wanted to be sure that a function returns only a certain :type of events. So I need to combine the ::common-event spec with a predicate...probably an s/and will suffice.


So I still keep running into situations where I have a spec for a domain level entity that is, say, a set of keywords and then the spec for the input level entity is a set of strings that are the names of the keywords... so my gut says to spec the input as (s/and string? (s/conformer (comp keyword str/lower-case)) ::domain-entity) with a generator of (fn [] (g/fmap name (s/gen ::domain-entity)))


But @alexmiller has said to avoid s/conformer so I suspect this is an anti-pattern, even tho' it's cropping up over and over again.


The other (anti-)pattern I hit is a domain spec for an int (int-in or whatever) and the input spec is string? and parse to long and the domain spec, again with a generator of fmap str over the domain spec generator...


Thinking about using a set of specs just for json/http params coercion here, then pass the result to domain specs, I think I prefer to keep both clearly separate.


makes it a bit easier to reuse also maybe


anyway, still have a ton of Schema code in our codebases, and still undecided on if/how to port it so far.


is there an equivalent of describe/form that will resolve specs recursively?


I mean resolve specs from the registry when it's composed from these


-> apparently not


(probably another anti-)pattern I encountered: setting a default value if nil when conforming, it's useful at input level too


(defn default [spec default]
   #(-> spec s/nilable (s/conform %) (or default))))


another annoying quirk, the following won't compile on alpha13: (defn foo [x] :clojure.spec/invalid)

ExceptionInfo Call to clojure.core/defn did not conform to spec:
:clojure.spec/args  (foo [x] :clojure.spec/invalid)
  clojure.core/ex-info (core.clj:4725)


makes it impossible to write a declared conformer ...


well you can create an alias first (def invalid :clojure.spec/invalid) and use it instead of :clojure.spec/invalid in the code, but that's kind of ugly


Question, do people add docs to specs? I’m making specs for some configuration data and I want to add meta data/documentation to individual specs to give more background information about the specific options


I don’t think you can add docs to specs…?


first time spec user here, trying to wrap my head around the best way of using namespaced keywords, never used ‘em before what’s the more correct pattern: having my keywords have namespaces that match my project’s namespaces, like :myapp.system.collision/foo? or having my keywords have namespaces that correspond to arbitrary concepts, unrelated to my app’s file/namespace structure, like :collision/foo?


so far i’m going with the latter, and it feels pretty good, but i’d just like to confirm with the experts 🙂


also - do you folks have any favorite example github repos that use spec, like, completely idiomatically? i’m switching my project over from schema, and some parts of the transition are straightforward, but other parts just feel like they could be done in a variety of different ways and i’d love to have a few canonical examples to look at and learn from


it's probably too early for that to exist =/


fwiw I'm leaning toward the latter of your two options as wel


@jrheard We’re creating new namespaces specifically for the data structure specs, and then requiring them into code namespaces as we need them. In a few places we have both data/specs and code. It’s whatever seems most appropriate.


BTW, if folks have any thoughts on my comments posted late last night (specifically about the pros and cons of using s/conformer)


(if you click that link, you’ll see two more follow-on comments)