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.