This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2017-06-06
Channels
- # aleph (15)
- # beginners (40)
- # boot (14)
- # cider (90)
- # cljs-dev (132)
- # cljsrn (25)
- # clojars (7)
- # clojure (188)
- # clojure-chicago (4)
- # clojure-dusseldorf (1)
- # clojure-greece (9)
- # clojure-italy (43)
- # clojure-russia (16)
- # clojure-sg (7)
- # clojure-spec (39)
- # clojure-uk (81)
- # clojurescript (170)
- # component (5)
- # core-async (7)
- # cursive (49)
- # data-science (65)
- # datascript (3)
- # datomic (27)
- # graphql (3)
- # hoplon (4)
- # instaparse (56)
- # klipse (129)
- # leiningen (1)
- # lumo (28)
- # off-topic (4)
- # om (15)
- # onyx (54)
- # overtone (7)
- # pedestal (7)
- # re-frame (9)
- # reagent (72)
- # ring (33)
- # ring-swagger (2)
- # spacemacs (1)
- # untangled (19)
- # vim (2)
- # yada (12)
I was surprised by the interaction of fspec
and instrument
. I was expecting instrument
to only check for spec'd function arg conformance, but it seems to additionally result in "exercising" passed functions. A gist with a concrete minimal example of what caught me off guard, where, in the last two forms evaluated in the REPL session, you can see arg conformance checking, followed by the function I'm passing being exercised: https://gist.github.com/mfikes/3ac5ca668b299e104490059ad0ccfcca
Perhaps ::number-sink
should not be defined using fspec
, but instead using ifn?
, as in
(s/def ::number-sink ifn?)
@mfikes the idea here is that if you spec a function arg, the only way to determine that the function you actually passed conforms is to exercise it. I have certainly used ifn?
as an alternate when that is not appropriate.
Makes complete sense, especially if the functions passed are pure. In my use case they were side-effecting, so ifn?
it is. I did like the fact that fspec
acts as good documentation, declaring the required shape of the passed functions precisely.
Here is my use case and context where this came up, if anyone is interested, which might be typical: https://github.com/mfikes/planck/blob/a7116251a62b05d6ecbeeaff1da809d123ff2b4e/planck-cljs/src/planck/socket/alpha.cljs#L11-L12
it’s possible to do BOTH too by declaring the fspec with the detailed spec, then providing a simpler override spec when you call instrument
It seems that (sort (gen/sample (s/gen (s/inst-in #inst "1800-01-01" #inst "2199-12-31")) 100))
has a very strong bias to generate dates within milliseconds of Jan 1, 1970.
thanks for the clarifications Alex
@deg would you want a uniform distribution between the two dates you gave?
@gfredericks Yes. (Definitely for date instances. Probably also for numbers where I've specified a range. OTOH, for unbounded numbers, I agree that clustering around zero is probably best)
It's tricky because test.check wants to be able to generate "simpler" instances when asked
So you're describing a generator that doesn't attempt to do that
Background: https://github.com/clojure/test.check/blob/master/doc/growth-and-shrinking.md
I hear ya. But, I don't believe that Jan 1, 1970 is an appropriate simplification nucleus for dates. The fact that it happens to have an internal rep of zero is not interesting for nearly all uses or tests of dates. Clustering around now is much more likely to catch interesting simple cases.
is there something like instrument
that also checks the :ret
value of functions? Just for catching the bad functions I write as close as possible to the problem
And, even for numbers, if I've specified a range, than interesting simple cases are likely to be the two end-points of the range and the mid-point.
@deg agreed; the unfortunate thing about "now" is it makes the generator nondeterministic
@gfredericks But, aren't generators already non-deterministic? I already can't assume that I'll get the same values each time. This change just means that I can't assume the same probability distribution either.
Ah, ok. Then I see the problem. In any event, the number range case can still be improved. And, for dates, it might make sense to center around 2015 or 2020, rather than 1970. To pick one (admittedly contrived) reason: it would be crazed for a test-generator tool written today to only test dates before the y2k problem!!!
Different question.... I just realized that s/tuple
needs a vector, and won't validate a list. Why? And, what is an idiomatic way to test for, say, a list of precisely two ints?
Actually, let me rephrase: what is an idiomatic way to test for a list of one int followed by one string?
@bronsa correct
@deg a tuple is inherently positional (indexed) whereas a list is not (it can only be traversed from the beginning).
but you can use (s/cat :i int? :s string?)
regex op specs can be matched against sequential stuff (lists, vectors, seqs, etc)
@deg there is no set of random dates that will be sensical for anyone. if you want to influence it, you should provide a generator that does so (via s/inst-in
). inst-in admittedly has a poor generator due to its non-uniform distribution. That is a bug (my fault) and should be fixed.
looks like I never logged that, so I just did https://dev.clojure.org/jira/browse/CLJ-2179
@alexmiller Understood. That Jira case nicely sums up all my concerns about inst-in. I think s/int-in should also be generated uniformly.
in my head I thought it did! but it does not.
will fix that as well
and I wrote it!
I'm just starting with spec (looked at it a few months ago, but only seriously these past couple of hours). So far, I like the direction a lot. Great work!
ok, patch attached that fixes both, hopefully will get a look at some point
can a spec be-used as a replacement for de-structuring a function? I know can spec/conform inside your function, but it would be nice if could refer to the symbols directly rather then the map. I suppose even with desctructring you need to refer to the keys…