This is exactly why we recommend that you not use conformers for coercion. 
Conformers were added primarily as a tool for building custom composite 
spec types (for example, we used it to build keys* from keys).

This is a common need though and I would be happier if spec did more to 
help you solve it in a way that minimized repetition and maximized the use 
of existing specs. I'm still thinking through what that would mean exactly. 
It's challenging right now to plug externally without rebuilding a 
significant part of spec, so that's obviously not ideal.

Ideally, you would be able to say the things that are important here:

- the spec of the incoming data (strings or whatever - JSON sourced is the 
major use case)
- the spec of the data I desire
- the coercion functions that can move from one to the other (there are 
probably a small number of these that are widely reused)
- some way to coerce+validate or coerce+conform

Building coercion into a single spec itself instead leads to the problem of 
not being able to know what the source data actually was, and that's really 
at odds with the spec philosophy and the notion of bidirectional conforming.


On Tuesday, February 20, 2018 at 4:41:38 AM UTC-6, Jan Rychter wrote:
>
> I've been using spec for a while now, in a reasonably large code base 
> (>30k lines of Clojure and ClojureScript) and there is an issue that bit me 
> several times.
>
> I use conformers for coercing data that is *almost* what I need, usually 
> when reading from JSON (RethinkDB). Common conformers are keyword and set. 
> And it works really well, except for one problem: there is no way to know 
> if data has been conformed or not.
>
> Calling s/valid? will tell me if the data is valid *if it has been 
> conformed*. But what if it hasn't? Can I use the data? Is it "valid" 
> according to the spec I wrote?
>
> This is a very real problem: I've spent considerable time chasing bugs 
> where there was a code path which did not call s/conform. The data passed 
> all validations done with valid? and the bug manifested itself far down the 
> road, where something expected a keyword instead of a string, or a set 
> instead of a vector.
>
> Here is a specific minimal example demonstrating what I'm talking about:
>
> (ns spectest
>   (:require [clojure.spec.alpha :as s]))
>
> (s/def ::test-spec (s/and (s/conformer keyword) keyword?))
>
> (s/conform ::test-spec "a") ;; :a
> (s/valid? ::test-spec "a") ;; true
>
> I expected the last valid? to return false, because my code does not 
> expect a string, it expects a keyword, according to the spec.
>
> I might be missing something, but I would much rather see valid? tell me 
> if the data is valid for use (as supplied) and have a separate 
> valid-when-conformed? which tells me if the data is, well, valid when 
> conformed. It seems to me that the current valid? that does two things is 
> confusing and not very useful for contracts.
>
> At the very least I'd really like to see a function that tells me if the 
> data is valid *as supplied*, as this is the function that I'd want to use 
> when enforcing contracts everywhere in my code.
>
> Alternatively, I could stop using conformers altogether, and write 
> explicit data conversion functions. That might not be a bad idea, but it 
> seems other people started using conformers, too, so eventually I'll hit 
> the same problem again.
>
> --J.
>
>

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