Fork me on GitHub
#clojure-spec
<
2017-12-10
>
Drew Verlee00:12:10

I'm somewhat confused about the exchange here: https://dev.clojure.org/jira/browse/CLJ-2116 If specs aren't meant for coercion from non clojure data structures to clojure datastructures. Then what is the recommended solution for coercion? Is the message that we shouldn't mix coercion to clojure data with validation of that data? Someone with more experience chim in please, but i feel like those things might overlap a great degree and if you cant compose the tool that is doing one with the other, then it feels like there is going to be a lot of confusing repetition.

seancorfield00:12:34

@drewverlee The philosophical reason is that if your spec does coercion, no clients of your spec can avoid that coercion, and that can lead to problems.

seancorfield00:12:50

FWIW, we use spec at work to validate form parameters which all come in as strings, so we have some very limited coercion in a few of our specs. We have ::long and ::double specs that accept both a number and a string that can be parsed to a number, a ::boolean spec that accepts both a Boolean and a string that can be parsed to a Boolean (under a documented set of rules), and a ::date spec that accepts both an instant and a string that can be parsed to an instant (again, under a documented, and limited, set of rules).

seancorfield00:12:39

That's about as far as I'd go with coercions in specs. Anything beyond that should separate the parsing operation out (and use spec to validate the resulting data structure), IMO.

seancorfield00:12:14

We also have a REST API where the payloads are parsed (with Cheshire, via wrap-json-params and wrap-json-body) and then validated -- separately -- which makes the specs much more robust and more usable, and makes explain-data much easier to process (for example, using it to turn spec failures into human readable messages). Coercion in a spec tends to make that last part harder (since you have more operations to pick apart).

seancorfield00:12:09

Coercion in specs also often causes more work in unform and generators since you need to be able to "de-coerce" validated data.

Drew Verlee00:12:19

@seancorfield That's reasonable. I suppose it works against what compjuri-api is going for. More to the point, i can't get compojure api to work anyway. Is there another restful api service i should look at? The more hand holding solution the better probably, as my use case is really bare bones.

seancorfield00:12:34

We've built our REST APIs with just bare bones Ring and Compojure. I haven't looked at compojure-api.

misha08:12:34

@borkdude have a look at s/nonconforming

ikitommi09:12:29

@seancorfield @drewverlee The CLJ-2116 tries to solve just that, by separating the coercion from specs. Specs to define the form and apply different coercion when needed, e.g. in the borders. int? should be coerced from string->number If provided as a path-parameter, not if provided as JSON body or within your own domain code. Solution to enable this would be simple.

ikitommi09:12:59

there is also CLJ-2251 on too If that which would make things fast.

ikitommi09:12:30

@drewverlee If you have trouble with the spec coercion with c-api, happy to help.

Drew Verlee14:12:56

Thanks @ikitommi i'll ask in another channel.

Drew Verlee14:12:15

@seancorfield i suppose its hard to see why i would use a spec on a string i had already successful parsed in most cases

(parse "drew,2") 
=> {:name "a" :siblings 2}
I have already discovered this line meets most of the specification * has two entries * second entry is a number If i want to build a spec about the clojure data to assert it has two entries and the first one is a string and the second is a number, i feel like i'm repeating information. I think the key point here is that, if i build a spec that does coercion on a string it wouldn't verify on the resulting structure. So its not really any more flexible or less work then separating out the coercion function and the spec.

genec15:12:14

Is there a way to use spec so that it can type hint function parameters during development? Coming from F#, it's something I really miss during development. Or is there a good post about spec demonstrating the Clojure way to keep track of data / types during development?

taylor15:12:47

I don’t have a good answer, but I also came to Clojure from F# ❤️ Personally, there were lots of things I missed early on from F# but over time I found myself not missing them so much

taylor15:12:13

I imagine you’re thinking of something that integrates into the editor? Spec does solve this problem with instrument but it happens as your code is executed, not when you’re typing it in

genec19:12:23

thanks - yes, I'm missing the type checking from F#. I don't see any reason why there could not be type hints for things that have been spec'd in Clojure. I'll keep looking into this. Out of curiosity, what's your development env? I was using Atom/Proto-Repl but found it a bit flaky so I've switched to Intellij / Cursive and really like it.

taylor21:12:09

I mostly use IntelliJ w/Cursive

Drew Verlee22:12:54

Ok some high level questions: 1. Is there value in exchanging name-spaced data across different systems? I feel like rich might have made a big deal about this and its gotten lost in the noise of me working with spec. 2. What would be the best way to transform a map with one namespace into another one with different namespaces. e.g

(s/def ::zoo (s/keys :car int?) 
(??? {:foo/bar 5 :foo/car 6} ::zoo)
=> {:foo/bar 5 :zoo/car 6}
This feels like what conform does, only i want it to not care about the namespace. Also that idea might be imply i'm doing something else wrong, so i'm open to suggestions.

Drew Verlee22:12:07

another way to handle my problem would be to unnamespace the map

Drew Verlee22:12:17

or i could not apply the namespace in the first place. I feel like these approaches have tradeoffs that probably dont matter in my situation but are interesting to think about.

Drew Verlee22:12:56

While i'm thinking about it. Is there a way to combine two specs for a hash-map into one?

Drew Verlee23:12:55

it would be that easy wouldnt it 😕 thanks @alexmiller

gfredericks23:12:46

pronounced "smerge"