Fork me on GitHub
#clojure-spec
<
2018-08-03
>
PB16:08:42

So question: I have the following...

(s/def ::name string?)
(s/def ::age (s/and integer? pos? #(< % 100)))
(s/def ::occupation #{:engineer :mechanic :manager :clerk})
(s/def ::person (s/keys :req [::name ::age ::occupation]))

(s/fdef do-it
  :args (s/cat :people (s/coll-of ::person))
  :ret (s/coll-of ::age))

(defn do-it
  [people]
  (map ::age people))
Running this does not work:
(stest/check `do-it)
=>ExceptionInfo Couldn't satisfy such-that predicate after 100 tries.  clojure.core/ex-info (core.clj:4739)
However, I can exercise the fn:
(s/exercise-fn `do-it)
([([#:gentest.core{:name "", :age 1, :occupation :manager}]) (1)]
 [([#:gentest.core{:name "A", :age 15, :occupation :engineer}]) (15)]
 [([#:gentest.core{:name "", :age 3, :occupation :manager}]) (3)]
 [([#:gentest.core{:name "nA0", :age 3, :occupation :clerk}]) (3)]
 [([#:gentest.core{:name "1ZJO", :age 3, :occupation :engineer}]) (3)]
 [([#:gentest.core{:name "80v", :age 20, :occupation :mechanic}]) (20)]
 [([#:gentest.core{:name "M", :age 98, :occupation :engineer}]) (98)]
 [([#:gentest.core{:name "", :age 2, :occupation :engineer}]) (2)]
 [([#:gentest.core{:name "drn9G", :age 59, :occupation :mechanic}]) (59)]
 [([#:gentest.core{:name "2p", :age 72, :occupation :clerk}]) (72)])
Why is this?

favila16:08:49

(s/and integer? pos? #(< % 100)))

favila16:08:03

this value space is too large

favila16:08:13

it can't create an efficient generator

seancorfield19:08:45

@petr (s/def ::age (s/int-in 1 100)) should solve that.

👍 4
favila19:08:28

ExceptionInfo Couldn't satisfy such-that predicate after 100 tries. almost always means there's an s/and with values generated from earlier predicates could not satisfy later predicates

favila19:08:57

very often you need a custom generator

favila19:08:57

btw it would be really nice to somehow have a generator associated with a predicate

favila19:08:47

is there some trick to this? I end up manually using s/with-gen everywhere I use a predicate (and having to remember to do that)