Fork me on GitHub
#clojure-spec
<
2018-12-04
>
alexmiller00:12:54

Well, not in spec

alexmiller00:12:05

Maybe there is in test.check

gfredericks00:12:17

Don't have any continuous stat distributions

gfredericks00:12:43

You could make them using fmap from something we do have

prozz00:12:53

yep, there is frequencies

gfredericks00:12:07

Unclear what kind of shrinking and growth you'd want in many cases

andy.fingerhut02:12:28

I think it is fairly straightforward to take a uniform random number generator for a float in the range [0, 1] and turn it into a generator for any distribution that has a function whose CDF you know how to evaluate. This page has what it claims is a very accurate approximation of the normal distribution CDF: https://web.archive.org/web/20151030215612/http://home.online.no/~pjacklam/notes/invnorm/#Pseudo_code_for_rational_approximation

andy.fingerhut02:12:43

I haven't checked out their implementation but kixi stats lib claims to implement this and many other distributions: https://github.com/MastodonC/kixi.stats

❤️ 4
jaihindhreddy16:12:53

Will the decomplecting of schema/structure from selections/context be there in 1.11, or will it get in earlier?

seancorfield16:12:52

@jaihindh.reddy The whole point of clojure.spec being developed and delivered as a separate library is that it is no longer tied to specific Clojure versions.

jaihindhreddy16:12:07

While that is true, spec does come in the clojure jar if I'm not mistaken, hence my doubt.

alexmiller17:12:32

no, it does not

alexmiller17:12:46

it’s a dependency, which you can independently update

alexmiller17:12:59

we’ve updated spec two or three times since 1.9 for example

alexmiller17:12:20

I expect that the new work will be available before 1.11

👍 8
alexmiller17:12:59

but it’s likely to be in a different namespace so will be a little trickier to use - we’ve spent some time thinking through that, and probably will require some more

urzds21:12:00

Is there some valid-or-explain function that I can easily use in my function's {:pre [(valid-or-explain ::spec %)]} context?

urzds21:12:34

Having s/valid? in there as suggested in the guide is nice, but if I cannot see what it is complaining about, it does not help much... 😞

taylor21:12:16

gotta be careful using s/assert in pre/post-conditions because if a nil input is valid, it'll return it (nil), causing the pre/post-condition to fail

taylor21:12:39

(because nil ≈ false)

taylor21:12:26

and also have to be mindful of s/*compile-asserts*

taylor21:12:52

@urzds if you want this behavior in pre/post-conditions it should be very easy to write a small function that does it

seancorfield21:12:58

Well :pre / :post only take effect if *assert* is true...

taylor21:12:35

*assert* is unrelated to s/*compile-asserts* AFAICT

seancorfield21:12:26

Yes, but the same caveat essentially applies -- you don't get the check in all cases.

👍 4
seancorfield21:12:31

Your point about nil is a good one -- I hadn't thought about that.

taylor21:12:33

it was a learned lesson 🙂

seancorfield21:12:13

If you want the check always performed, write it as code in the body of the function. If s/assert works for you (not nil values, (s/check-asserts true) has been run), that's probably a reasonable approach -- otherwise you'll have to write your own variant of s/assert. Or perhaps write an fspec for the function and instrument it?

jumar08:12:55

You can also set it via system property clojure.spec.check-asserts

urzds21:12:39

What would be a good way to check whether a collection contains certain elements? I.e. I have [{:name "a"}{:name "b"}{:name "c"}] and I want to ensure that the collection always contains at least one element with :name "a" and one with :name "b".

urzds22:12:01

Additionally, I would like to ensure that each :name only occurs once.

taylor22:12:11

you could use s/and with an extra predicate for those conditions

urzds22:12:55

(Also note: The element's maps contain more keys than just :name, so I cannot use :distinct.)

dchelimsky22:12:31

Would it be reasonable to change the structure to a map where name moves up to keys?

dchelimsky22:12:01

I don’t assume it is reasonable. Just asking if it is.

urzds22:12:21

Was thinking about that initially, but I want to expose the data structure using GraphQL, and that can afaik only query for predefined keys.

dchelimsky22:12:00

I’ve run into that recently :)

taylor22:12:31

maybe something like this for your uniqueness constraint, and easy to add your other constraint

(s/def ::names
  (s/and (s/coll-of (s/keys :req-un [::name]))
         #(apply distinct? (map :name %))))
(s/explain ::names [{:name "a"} {:name "b"}])
(s/explain ::names [{:name "a"} {:name "a"}])

urzds22:12:35

@taylor: (s/and #(some (fn [x] (= (:name x) "a")) %) #(some (fn [x] (= (:name x) "b")) %))?

taylor22:12:16

(s/def ::names
  (s/and (s/coll-of (s/keys :req-un [::name]))
         #(let [names (map :name %)]
            (and (apply distinct? (map :name %))
                 (clojure.set/superset? (set names) #{"a" "b"})))))
here's another way, not necessarily any better though

urzds22:12:54

At least it becomes more clear what we're trying to do.

taylor22:12:26

and you may prefer to break each condition into its own predicate like your first example

taylor22:12:43

as opposed to packing multiple conditions into one predicate

urzds22:12:31

So I can combine the ::specs instead of having the big inline function?

taylor22:12:51

the explain output for invalid inputs will likely be easier to understand if the predicates are separated

taylor22:12:35

i.e. if they're all combined the explain output isn't going to tell you exactly which condition failed

urzds22:12:03

I guess there is no way to reuse names in both specs?

urzds22:12:31

Looks horribly complicated, I guess I'm missing the easy syntax...

alexmiller22:12:28

coll-of has a :distinct option fyi

alexmiller22:12:55

oh, I guess you’re a level off of that