Fork me on GitHub

Hey folks, can you help me to understand why I can't gen/generateor gen/sample:

(def email-regex #"^[a-zA-Z0-9._%+-][email protected][a-zA-Z0-9.-]+\.[a-zA-Z]{2,63}$")

(spec/def ::email-type (spec/and string? #(re-matches email-regex %)))
(spec/def ::uuid int?)
(spec/def ::first-name string?)
(spec/def ::last-name string?)
(spec/def ::email ::email-type)
(spec/def ::phone #"^\d{12}$")

(spec/def ::person (spec/keys :req [::first-name ::last-name ::email]
                              :opt [::phone]))
(gen/generate (spec/gen ::person))

 Show: Project-Only All 
  Hide: Clojure Java REPL Tooling Duplicates  (13 frames hidden)

1. Unhandled clojure.lang.ExceptionInfo
   Couldn't satisfy such-that predicate after 100 tries.
   {:pred #function[clojure.spec.alpha/gensub/fn--1876],
    {:gen #function[clojure.test.check.generators/such-that/fn--40141]},
    :max-tries 100}


Have you tried exercising your specs?


Couldn't satisfy such-that predicate after 100 tries


Thats the key part to the error message


I would just go through each def and see if they can produce a result


my bet is on email and phone


yes i would agree


If the predicate is too hard to er fufill? based on random string input, don't you usually just create a generator for those complicated predicates?


also i'm not all that sure how (spec/def ::phone #"^\d{12}$") works


If you exercised ::phone what would you get? thats a pattern isnt it :thinking_face:


Unable to construct gen at: []


Thats what i get


for (s/exercise ::phone)


Just saw now, the answers, will be right back after doing what you said 😄


So then I think for the email, its just as simple as, the string generator can't create a random entry that matches your regex


which makes sense right? as even after 100 times its going to be difficult to randomly create an email i think haha


After trying to exercise each attribute, it appears that ::phone and ::email-type can't be exercised


ahh thanks that was the link i was looking for. :thumbsup:

seancorfield17:11:37 has a generator for regex strings that I've found very useful.


I am trialling offloading some extra logic onto s/or and would like some collective opinion, if y'all were so kind. Suppose I have a spec defined like this:

(s/or :x :x/item
      :y :y/item)
Now suppose I add x1 and want to combine it with x at some point; so let's say I start making the semantic distinction between what this thing is and what it can be combined into:
(s/or [:additive :x] :x/item
      [:additive :x1] :x1/item
      [:multiplicative :y] :y/item)
Now, suppose further that I want to encode the order in which the respective operation should be defined. Now I'm thinking it would be really useful to be a bit more descriptive in my tags, so why not use a map?
(s/or {:type :additive
       :operand-type :x
       :precedence 1}

      {:type :additive
       :operand-type :x1
       :precedence 2}

      {:type :multiplicative
       :operand-type :y}
Now I'm thinking, should I simply add this via a conformer, keeping the tags simple (and thus transforming them at a higher level elsewhere in the spec) or do I keep this? This might all seem like a contrived example - and it is, because my use case isn't algebraic operations, but rather data merging, and thus it's really important to define what order each data types should be merged in, and what the parent type is, so that the correct merge strategy is applied. My question is - am I really using s/or in a way I shouldn't be or would you still consider this ok?