Got it. Thanks for the answers.
I still feel that the global registry for specs is weird. It seems so easy to have namespaced keyword conflicts coming from various namespaces, specially in big projects where people don't know well each other's work. It is quite different from the regular Clojure file philosophy, when you stick to "require", where a name is either declared in the standard library, in the current scope or explicitly required. Le jeudi 17 novembre 2016 18:25:57 UTC+1, Francis Avila a écrit : > > Your spec names need different namespaces, but your functions do not: > > > (s/def :catalog-a/type #{"a" "b" "c"}) > (s/def :catalog-a/ref string?) > > (s/def :catalog-b/type #{:x :y :z}) > (s/def :catalog-b/ref number?) > > > Then you need to say that the keys are unqualified when they appear in the > map for this function: > > > (s/fdef get-product-from-catalog-a > :args (s/keys :req-un [:catalog-a/type :catalog-a/ref] > :ret any?) > > (s/fdef get-product-from-catalog-b > :args (s/keys :req-un [:catalog-b/type :catalog-b/ref] > :ret any?) > > In general clojure spec tighly binds key names in maps to spec names and > it is very hard to separate them. This is a formal part of its rationale, > expressed as "Map specs should be of keysets only" > <http://clojure.org/about/spec#_map_specs_should_be_of_keysets_only>. > > There is a case I do not understand how to do well, where I want a > specific function to accept a map with a specific specced key, but I want > that key's value to conform to some strict subset of possible values as > well. In essence, I want to "subclass" the key. > > The options I see are: > > 1. Make a different spec based on the parent spec but adding > refinements, then make and spec adaptor functions which do nothing but > change the key (and validate). I.e., do the respec dance before the code. > 2. In the body of the function, call another function that accepts the > spec as a value (rather than in a map), and refine the value there. Your > outer function will still have to accept other values and handle them > somehow (signal error, throw, whatever). > > Both of these are awkward when dealing with existing systems which to not > consider specs to be of keysets only. In particular, we deal with a > specification called FHIR <https://www.hl7.org/fhir/> whose type model > allows "profiles", which are declared on an instance (e.g. a map would have > a type key for the base type and optionally a "profiles" key which is any > additional specs to which the map must conform). A profile is essentially a > restriction of the instance's basic types (they can never extend) such that > any profiled instance must always conform to the base type's spec. E.g. if > a field is allowed to have values "a" and "b", the profile may say that > field may only have "a". So in essence we want maps to potentially conform > to multiple specs at once: the base spec which is the keys in the map, and > a profile spec which uses the same keys but may add additional > restrictions. I have not thought of a good way to express this in > clojure.spec. > > On Thursday, November 17, 2016 at 10:54:18 AM UTC-6, damien....@gmail.com > wrote: >> >> I forgot the :req-un. >> >> (s/fdef get-product-from-catalog-[a|b] >> :args (s/keys :req-un [::type ::ref]) >> :ret any?) >> >> >> >> -- You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en --- You received this message because you are subscribed to the Google Groups "Clojure" group. To unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.