This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2016-07-15
Channels
- # admin-announcements (2)
- # beginners (93)
- # boot (34)
- # capetown (1)
- # cider (15)
- # cljs-dev (30)
- # cljsjs (9)
- # clojars (8)
- # clojure (199)
- # clojure-austin (3)
- # clojure-france (3)
- # clojure-greece (2)
- # clojure-italy (46)
- # clojure-quebec (7)
- # clojure-russia (2)
- # clojure-spec (76)
- # clojure-uk (16)
- # clojurescript (43)
- # core-async (7)
- # cursive (14)
- # data-science (1)
- # datascript (4)
- # datomic (3)
- # devcards (60)
- # editors (5)
- # funcool (5)
- # garden (3)
- # hoplon (32)
- # immutant (22)
- # jobs (1)
- # lein-figwheel (21)
- # leiningen (1)
- # mental-health (11)
- # mount (2)
- # off-topic (6)
- # om (16)
- # onyx (15)
- # re-frame (43)
- # reagent (20)
- # rum (18)
- # specter (37)
- # sql (2)
- # testing (8)
- # untangled (7)
- # yada (19)
Like (s/* ___)
?
I suppose the validation is the sticky part
I think that's what s/every is for, if you need incomplete validation
I guess technically s/* isn't the same thing as infinite
With s/+
I just got an infinite loop. (It tries to check every element in the infinite sequence I guess) s/every
looks promising.
Or, it works to validate it like this (s/valid? (s/every :my/pred) (repeat my-item))
but not inside :args
in s/fdef
. Any ideas?
do you just mean that it's not validating at all because you haven't instrumented the function? or is it breaking in some way?
@gfredericks It goes into an infinite loop when I put it in my fdef
and then execute the function.'
just starting to play with spec... How would you say "A map must have either the keys :foo
or :bar
or both (but not neither)"
guessing I just need to supply all three combos
Yeah use s/or
the guide has an example http://clojure.org/guides/spec#_instrumentation
makes perfect sense - thanks
@rickmoynihan: there is direct support for or in keys:
the use of s/or in the example from the guide (mentioned above) is to distinguish 2 different kinds of maps
thanks richhickey 🙂
Am I right in thinking that the 'or
symbol there is actually clojure.core/or
- and spec interprets the symbol itself as meaning or?
ahh yes keys
is a macro
‘or’ and ‘and’ are syntax inside keys
when I first saw spec, I wondered why you hadn't done that! Super nice!
symbols are data too
@glv have any more info on test.check fns “ignoring size guidance”? Starting to read the source now, and it looks like we might need to explicitly opt in to sized
in some places
A lot of the generators for built-in predicates use large-integer*
from test.check, which doesn’t use sized
. Perhaps instead use the more specialized things like pos-int
, s-pos-int
, etc.?
@glv I am confused because large-integer*
calls large-integer**
which does use sized
@glv your proposal still may be the right thing, I just want to understand why we are getting the current behavior
@glv it looks to me like s-pos-int
use size on integers, and large-integer**
uses size on bit count
and if we switch to s-pos-int we would never get larger values
That might explain the weird, long-cycle behavior of (s/gen int?) in that example I pasted yesterday.
(apply max (gen/sample gen/int 1000000))
=> 99
grr, maybe neither growth pattern is ideal
Right. I think (I’m no expert) that’s why test.check has both. pos-int (and family) for integers that are used as sizes for things, and large-integer for integers used in mathematical functions.
whereas spec has specific (int-in et al) and non-specific (pos-int et al)
And the only reason that kind of annoys me is that those are generators only, not specs. It doesn’t seem good to have to specify a custom generator for such a common case. (My hunch, which may be wrong, is that in most systems, functions that build and manipulate data structures are more common than functions that do complex math on integers.)
@glv in cases where you don’t specify, I would like to see it grow more slowly, but still grow
hitting the hammock on this one
to be more honest, grabbing some lunch 🙂
but we do have a hammock in the office
@stuarthalloway: Oh wait … of course int-in
is a spec, not just a generator. The real issue is that I want a large upper-bound in production, but smaller in tests (because a 100x100 matrix will be much slower with a negligible chance of exposing bugs that wouldn’t be seen in a 20x20 matrix over a bunch of tests. But there’s no reason to restrict it so tightly outside of the tests. (Maybe my case is just weird and special. But I do think the existing growth pattern is surprising, and I strongly suspect that it negatively affects shrinking.)
So I’m seeing something odd in the interaction of s/every-kv
and s/conform
.
(s/def ::path-spec (s/cat :method #{:get :post} :path string?))
=> :io.aviso.config.spec/path-spec
(s/def ::paths (s/every-kv ::unqualified-keyword ::path-spec))
=> :io.aviso.config.spec/paths
(s/conform ::paths {:one [:get "foo"]})
=> {:one [:get "foo"]}
I’d expect that to be {:one {:method :get :path “foo”}}
.BTW:
(s/def ::unqualified-keyword
(s/with-gen
(s/and keyword?
#(-> % namespace nil?))
gen/keyword))
@hlship: Why not use simple-keyword?
Use s/map-of
instead.
I don’t think every-kv
conforms the values?
Yeah, just confirmed via the docstrings — map-of
"Unlike every-kv
, map-of will exhaustively conform every value." — every-kv
(based on every
) "Note that every
does not do exhaustive checking, rather it samples *coll-check-limit*
elements. Nor (as a result) does it do any conforming of elements."
(I did not know that before you asked so, thank you, "learn something new every day" 🙂 )
@hlship: Docs for simple-keyword?
are here. It is new in 1.9. https://clojure.github.io/clojure/branch-master/clojure.core-api.html#clojure.core/simple-keyword?
So you can do without ::unqualified-keyword
and just use simple-keyword?
directly in map-of
.
@glv so test.check does two flavors of things:
1. built-ins that bottom at choose use the size argument twice, to control the rate of growth and to limit the values reached
(->> (gen/sample-seq gen/s-pos-int 1000)
(take 200))
2. built-ins that bottom at large-integer use the size argument only once, to control (approximately) the number of bits allowed
(->> (gen/sample-seq (gen/large-integer* {:min 1 :max 1000}) 13)
(take 200))
note the 13
(bits) vs 1000
(value) passed as size to gen/sample-seq
spec does not (yet) even provide a path to setting the size argument
@glv ignore that crap explanation ^^. Bottom line is we want a generator that will grow nicely with a default max-size, working on it.
@stuarthalloway: Right, sounds great. Thanks!