Amazing! 

Lot of thanks Josh! This solves everything. It is even written in the API 
doc, but I missed the important piece of "(possibly converted) value"...

With best regards
Plamen

On Tuesday, October 11, 2016 at 8:49:16 PM UTC+2, Josh Tilles wrote:
>
> I think you’re looking for conformer 
> <http://clojure.github.io/clojure/branch-master/clojure.spec-api.html#clojure.spec/conformer>;
>  
> the spec it produces will pass along the converted value instead of the 
> original input. It could be used like:
> (defn str->double [s]
>   (try
>     (Double/valueOf s)
>     (catch NumberFormatException _
>       :clojure.spec/invalid)))
>
> (s/def ::transforming-check (s/and string? (s/conformer str->double) ::
> bigger-than-zero?))
>
> I hope that helps with your original problem, but I’ll defer to the more 
> experienced folks here for your questions about the spirit/aim of 
> clojure.spec.
>
> On Tuesday, October 11, 2016 at 2:30:18 PM UTC-4, plamen...@gmail.com 
> wrote:
>>
>> Hello,
>>
>> I have a problem which is probably not in the spirit of clojure.spec as 
>> being a library for "only" checking/generating valid values, but of 
>> substantial practical value for my use case:
>>
>> Let say I have a function for checking if a double precision number is 
>> parsable from a string (where possible performance penalties because of 
>> communicating non-parsable strings through try/catch in the implementation 
>> is not part of my question):
>>
>>
>> (defn str-parsable-double? [s]
>>   "Note the IMPLIED transformation from string to a double"
>>   (try
>>     (Double/valueOf s)
>>     (catch NumberFormatException e
>>       false)))
>>
>>
>> and have a spec using this function:
>>
>> (s/def ::str->double str-parsable-double?)
>>
>>
>> We could actually chain checks for a single value as in:
>>
>> (s/def ::str->double (s/and string? str-parsable-double?))
>>
>> and we could check for the conformity of a value as per:
>>
>> (s/conform ::str->double "3.14")
>> => "3.14"
>> and 
>> (s/conform ::str->double "Pizza")
>> => :clojure.spec/invalid
>>
>> Until now everything is ok, now my the questions:
>>
>> In my real world example I need a chain of a combination of checks and 
>> transformations in the following way:
>> ::check1 ::check2 ::check-and-transform3 ::check-4-on-transformed-value 
>> ::check-5-on-transformed value
>> or something like
>> (s/def ::transforming-check (s/and string? ::str->double ::bigger-than-zero? 
>> ::smaller-than-pi ... etc ...))
>>
>> As the result of 
>> (s/conform ::str->double "3.14") is the input value as a string instead of 
>> the result, I would need implement ::bigger-than-zero? and the rest of the 
>> checks as operating on strings, which would mean that I need in each check 
>> to transform the string into a double, which in my case is for performance 
>> reasons bad.
>>
>> On the other side I would be able to do the checks in a 2 step fashion, 
>> which goes against my understanding of the aim of clojure.check to be able 
>> to create through composition a single set of validations for a single value.
>> This also doesn't solve fully the problem with the multiple parsing of the 
>> first data type before the transformation: a parsing happens in the 
>> ::str->double step as well in the then explicit transformation step before 
>> the final checks based then on the actual double.
>>
>> So - is there a way to compose checks in a single one, where some of them 
>> change the underlying type of the value for subsequent validations (I may 
>> miss something in the Clojure documentation, and pointers to it would be 
>> very welcome)?
>>
>> If not - why s/conform returns the input value instead of the result value? 
>> As being on the caller site of s/conform I know what I passed and I know 
>> what s/conform would give me in the negative outcome of the validation.
>> If s/conform while iterating/recursing through the actual spec would apply 
>> the checks on returned values of previous checks instead always on the input 
>> - the problem would be solved, without negatives for the calling sites (as 
>> because of the previous sentence).
>> This could be solved for example (not sure if I see every detail yet, but at 
>> least as a pointer) in that in the clojure.spec code
>>
>> Spec
>> (conform* [_ x] (let [ret (pred x)]
>>                   (if cpred?
>>                     ret
>>                     (if ret x ::invalid))))
>> the value of cpred? could be passed from the calling site (or if don't miss 
>> something be even per default true).
>>
>> In any case, I would be thankfull for any suggestions solving both proplems: 
>> how to express such checks in a good way and how to avoid reparsing values 
>> again and again (where the current example is for just strings to doubles, 
>> but the actual problem could involve any transformations on the value incl. 
>> type).
>>
>> With best regards
>> Plamen
>>
>>
>>
>>
>>
>>

-- 
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