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 [email protected]
Note that posts from new members are moderated - please be patient with your
first post.
To unsubscribe from this group, send email to
[email protected]
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 [email protected].
For more options, visit https://groups.google.com/d/optout.