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.

Reply via email to