Thanks Alex, I am surprised by info that *"s/and (and all of the spec forms) are macros to facilitate capturing the spec form for use in s/form and error reporting." *but everything makes sense considering it.
Marián On Thursday, May 18, 2017 at 6:35:46 PM UTC+2, Alex Miller wrote: > > > > On Wednesday, May 17, 2017 at 3:02:17 PM UTC-5, marian...@vacuumlabs.com > <javascript:> wrote: >> >> Hi, >> >> I am writing a function that transforms Specs to another formats (similar >> to the JSON Schema). Assuming from this post >> <http://www.metosin.fi/blog/clojure-spec-as-a-runtime-transformation-engine/>, >> >> I am not the only one. There is no surprise that I am using >> clojure.spec/form. Unfortunately I am not fully satisfied with its >> output. To illustrate the problem let's suppose that my transformer will be >> used by a third person who like to write its own spec-generating helpers: >> >> (require '[clojure.spec.alpha :as spec]) >> >> (spec/def ::forgivable-keyword (spec/conformer (fn [x] (cond (keyword? x) >> x >> (string? x) >> (keyword x) >> true >> ::spec/invalid)))) >> >> (defn kw-enum [& enum-values] (spec/and ::forgivable-keyword (apply >> hash-set enum-values))) >> >> > s/and (and all of the spec forms) are macros to facilitate capturing the > spec form for use in s/form and error reporting. > > In this case, (apply hash-set enum-values) is not either a predicate or a > set and thus is not a valid spec to use in s/and. > > I presume what you're looking for is the ability to dynamically create > specs - for this, please consider using either eval or a macro. > > > >> Cool! Let's look how can my transformer cope with it! >> >> (spec/form (kw-enum :a :b :c)) >> ; (clojure.spec.alpha/and >> :my-ns/forgivable-keyword (clojure.core/apply clojure.core/hash-set >> enum-values)) >> >> Ouch! Have I just seen a local symbol in the form? I am sorry third >> person, I won't be able to transform the output of your spec-generating >> functions. Unless they are macros: >> >> (defmacro kw-enum [& enum-values] `(spec/and ::forgivable-keyword ~(apply >> hash-set enum-values))) >> >> (spec/form (kw-enum :a :b :c)) >> ; (clojure.spec.alpha/and :my-ns/forgivable-keyword #{:c :b :a}) >> >> This approach looks better. How does it work in combination with other >> specs? >> >> (spec/form (spec/nilable (kw-enum :a :b :c))) >> ; (clojure.spec.alpha/nilable (my-ns/kw-enum :a :b :c)) >> >> There we are. A third-person's function is in the form. We could use eval to >> resolve it, but do we want to? >> > > Sure. It resolved to a spec last time, why not this time? OR, why do you > need to resolve it at all? (this to some degree depends on the use case) > > >> It has been already evaluated once. What if there are some side effects? >> > > Then I'd say you already have more important problems. > > >> Practically, one has no option to write spec-generating function and >> maintain usability of the spec/form at the same time. Therefore one of >> four situations must have happened. Either I got something wrong, Specs are >> not meant to be introspected, Specs are not meant to be generated or >> spec/form is badly designed. Which one is it? >> > > Seems to me like you can generate and introspect this fine. I think that > if you are introspecting spec forms, you will encounter resolved symbols > referring to functions. How you approach the use of those depends on your > context. > > Another option still coming (work in progress) is to use specs on spec > forms (CLJ-2112) to create conformed spec data, then s/unform back to a > spec form. > > >> >> (In the case of the fourth one I have some suggestions, but lets keep >> them for later conversation) >> >> Thanks for your time >> >> Marian >> > -- 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.