Fork me on GitHub
#clojure-spec
<
2016-06-05
>
Alex Miller (Clojure team)00:06:24

the terminology drifted a bit during dev

adambros02:06:49

Is there anything planned in terms of having predicates/specs with custom error messages/data? I’m speaking from a validation perspective, because the alternative is to wrap explain-data

adambros02:06:40

it also seems that for related reasons, I would be writing a conform-or-explain! function that throws with explain-data when the conform fails

adambros03:06:16

While I’m asking, it would be a useful feature to be able to somehow get the path at which a predicate is being run. This one is coming up as I’m trying to secure a datomic transaction wrapper by looking up if a user has access to a certain :db/id that’s potentially nested within a map.

seancorfield03:06:59

@adambros: which alpha are you using? I thought they'd added a path result in explain in one of the later alpha builds.

adambros03:06:58

i’m referring to accessing the path from within the predicate

adambros03:06:44

might be bad idea (TM) but its something that would ameliorate my problem

seancorfield03:06:55

But each predicate only knows what it is called on -- it can't know the whole path, since a predicate is a general function.

seancorfield03:06:22

If your predicate is string? for example...

adambros03:06:30

it could if there was a dynamic var *path* or something. I think i could solve this another way so its fine

seancorfield03:06:08

Dynamic vars are evil 😆

adambros03:06:49

im more interested in my other questions, so i probably shouldn’t have asked about it

seancorfield03:06:59

Ok, what are the other questions? I think I missed those...

adambros03:06:53

custom error message for predicates/specs something like (s/def :title (s/either string? {:message “invalid title"}))

adambros03:06:31

where either’s predicate either succeeds or puts the 2nd argument in explain-data’s result

adambros03:06:19

and the other was about a potential builtin for validation, conform-or-explain! that throws if it cant conform

seancorfield03:06:07

I get the impression from the discussions here that explain-data is indeed the preferred basis for any custom error messages. I think there is a JIRA ticket for something like conform-or-explain tho'... let me go look...

seancorfield03:06:43

Hmm, no, maybe it was just a discussion on the clojure-dev mailing list.

adambros03:06:26

seems like it’d be a simple wrapper, with an extra arity for a function to call with the data when it fails

adambros03:06:56

(defn conform-or-explain [spec x & [on-fail]] ...)

adambros03:06:42

by default it’d throw the error in an ex-info

seancorfield03:06:30

Ah, I remember now, it was a valid or explain wrapper that was discussed -- for use in :pre assertions.

seancorfield03:06:04

But, yeah, I think the wrapper is so easy to write -- and some folks would want to throw explain-data and some would throw explain as a string so I don't think there's a one size fits all here.

adambros03:06:19

fair enough, sounds like I just need to have some sort of spec namespace that declares these wrappers

seancorfield03:06:05

One of the great things about Clojure: it's easy to write an adapter layer to make the supplied libraries match each specific application's needs 🙂

seancorfield03:06:51

We have a bunch of wrappers at World Singles. We have several of our own string functions in a namespace that supplements clojure.string.

seancorfield04:06:15

We also have some collection functions, a bunch of date stuff, wrappers around system level stuff. Wrappers around JDBC stuff (and, heck, I maintain clojure.java.jdbc!).

benzap13:06:35

anyone know of a good way to define a spec for an atom holding a piece of structured data?

benzap13:06:49

seems like I would need to deref in order to perform the spec, so a lot of wrapping even for simple checks

nwjsmith14:06:55

@benzap: I think someone asked this a few days ago and the answer was "There isn't because atoms aren't 'data'". IIRC there was also a suggestion to take a look at coll-of, which might have some bits you could crib to implement an atom-of. I might look into this today.

Alex Miller (Clojure team)15:06:41

personally, I think you should work with state by a) defining your problem in terms of data b) writing nearly every function as a pure function from data to data c) isolating the use of stateful entities to as small number of functions as possible d) focusing on writing great specs for b in terms of a

Alex Miller (Clojure team)15:06:42

not every function has to have a spec

gfredericks18:06:40

has anybody started a clojure.spec utility library yet because I keep thinking about doing that

gfredericks18:06:00

should probably call it spook

Alex Miller (Clojure team)19:06:21

you may want to check your urban dictionary before you venture down that path

gfredericks19:06:58

urban dictionary has all the best words

Alex Miller (Clojure team)19:06:46

totally on a tangent, the urban dictionary was hiring for a full stack clojure position recently

Alex Miller (Clojure team)19:06:02

spock is much better :)

Alex Miller (Clojure team)19:06:22

although I think there is a scala (or groovy?) testing library called that already

gfredericks19:06:50

splec, shplec

bronsa19:06:04

shpec sounds like something sean connery would say

gfredericks19:06:23

okay so we already have a mascot

gfredericks19:06:23

(require [com.gfredericks.shpec :as s'])

bronsa19:06:08

just realized 'foo' is valid clojure

gfredericks19:06:27

I only wish the syntax highlighters were more often aware of that

gfredericks19:06:40

...because I use that all the time

mfikes19:06:18

Replete (standalone ClojureScript iOS app) has an update in the App Store with support for cljs.spec.

stathissideris20:06:42

is there any way to make s/cat specs generate a vector?

gfredericks20:06:12

stathissideris: both s/coll-of and s/tuple can generate vectors -- are either of those usable for you?

stathissideris21:06:33

@gfredericks: tuple would work for my validation, but ideally I would like to keep the destructuring that s/cat provides

gfredericks21:06:13

what you want is a way to gen/fmap the default generator

Alex Miller (Clojure team)21:06:35

use with-gen to override the generator with fmap

gfredericks21:06:48

alexmiller: but how do you get the default generator to pass to fmap?

Alex Miller (Clojure team)21:06:39

well you could call s/gen on the original spec but I guess you may end up repeating yourself

gfredericks21:06:52

that was the hack I was about to suggest

gfredericks21:06:12

we can put a helper for this into shpec

stathissideris21:06:15

thank you both! I'm not very well-versed with test.check, but I'm saving this part of the log so that I can go do some reading. It will hopefully make more sense after that 🙂

gfredericks21:06:41

stathissideris: we're suggesting (s/def ::foo <definition>) (s/def ::foo (s/with-gen <definition> (let [g (s/gen ::foo)] #(gen/fmap vec g))))

gfredericks21:06:50

and <definition> being there twice is the repetition alex mentioned

stathissideris21:06:15

great thanks, I'll give it a go. In my case <definition> is not too long, so it could be ok

gfredericks21:06:08

could even try factoring it out to a let and see if that works

stathissideris21:06:56

...or even a macro is that doesn't work

gfredericks21:06:41

alexmiller: the default generator for s/and is necessarily pretty hacky; should there be some documentation somewhere suggesting an override?

gfredericks21:06:14

somehow overriding test.check's normal error message for such-that would be a fancy approach

Alex Miller (Clojure team)21:06:36

I think there is some desire to have a better (programmatic) way to have a conversation about filtering with such-that than just boolean yes/no

Alex Miller (Clojure team)21:06:03

but I'm sure Rich would have more to say about that

gfredericks21:06:04

that sounds sooper fancy

gfredericks21:06:46

alexmiller: do you know if recursive specs is the only reason for the no-arg-function-returning-a-generator pattern?

Alex Miller (Clojure team)21:06:17

Stu worked on that but I assume the dynamic loading is another aspect

gfredericks21:06:45

oh that sounds plausible