Fork me on GitHub
#clojure-spec
<
2017-11-24
>
johanatan02:11:12

I'm getting ExceptionInfo Couldn't satisfy such-that predicate after 100 tries. clojure.core/ex-info (core.clj:4744) for a spec generator that seemingly should be fairly trivial:

(s/def ::snake-cased-alpha-numeric
  (s/with-gen
    (s/and string? #(re-matches #"[a-z|\_|0-9]+" %))
    #(gen/fmap (fn [v] (apply str v)) (gen/vector (gen/frequency [[1 (gen/return \_)] [9 gen/char-alphanumeric]])))))
(s/def ::required? boolean?)
(s/def ::property-attrs
  (s/keys :req-un [::required?]))
(s/def ::events-schema
  (s/map-of integer?
            (s/map-of ::snake-cased-alpha-numeric
                      (s/map-of ::snake-cased-alpha-numeric ::property-attrs))))
> (gen/sample (s/gen ::events-schema))
ExceptionInfo Couldn't satisfy such-that predicate after 100 tries.  clojure.core/ex-info (core.clj:4744)

johanatan02:11:47

[I added the with-gen on snake-cased-alpha-numeric with it being the most complicated primitive in there and still get the error]

danielcompton02:11:11

@johanatan can you generate any of the leaves?

johanatan02:11:55

> (gen/sample (s/gen ::property-attrs))
({:required? false} {:required? false} {:required? true} {:required? true} {:required? true} {:required? true} {:required? false} {:required? false} {:required? false} {:required? true})

johanatan02:11:06

> (gen/sample (s/gen ::required?))
(false true true false true true false true true false)

danielcompton02:11:20

what about snake-cased? that looks like the tricky one

johanatan02:11:40

> (gen/sample (s/gen ::snake-cased-alpha-numeric))
("zno" "n7" "_" "3" "_" "c" "8_" "5i" "k7q" "i")

johanatan03:11:55

oh, this may be it:

johanatan03:11:58

> (gen/sample (s/gen ::snake-cased-alpha-numeric) 100)
ExceptionInfo Couldn't satisfy such-that predicate after 100 tries.  clojure.core/ex-info (core.clj:4744)

danielcompton03:11:14

try (s/map-of integer? ::snake-cased-alpha-numeric)

johanatan03:11:20

perhaps there is a bug where my regex doesn't match values generated with the with-gen-specified generator

johanatan03:11:42

i've seen that error when the two are mismatched: i.e., when the spec and the generator for it are not perfectly aligned on what is acceptable or not

gfredericks03:11:45

I forget what the implications of jinx are

gfredericks03:11:51

do I have to not talk now for some time period

danielneal08:11:15

I think you can't talk until someone says your name three times

gfredericks12:11:34

the same person? back-to-back in quick succession?

danielneal13:11:49

aw you're right that's totally underspecified

danielneal13:11:48

Traditionally, a jinx is ended when anyone speaks the jinxed person's name. However, a common variation says that only the jinxer can free the jinxee from their obligation to remain silent. (This is sometimes called a "private jinx" or "jinx personal lock".)

gfredericks19:11:21

a private jinx sounds a lot less interesting

johanatan03:11:01

hmm, yea, i'll give that a try. thx!

johanatan03:11:57

that fixed it. was able to successfully generate 1000 at once

johanatan03:11:52

there is a bug in my regex though. noticing that pipes are ending up in the output. probably was the original problem

danielcompton03:11:48

buy me a coke I think, although I probably owe you the drink. Edit: this was about the jinxing

johanatan03:11:03

haha, definitely. i would even get you a beer if you prefer

johanatan03:11:21

this was my intended regex, btw: #"[a-z0-9\_]+"

qqq05:11:29

does clojure have any naming convention regarding fn names that end in a '-' ?

qqq05:11:08

for ecample, I have (defn node->svg ...) and I would like to define a helper function named (defn node->svg- ...) but intuitively, functions that end in '-' seem like a bad idea

seancorfield05:11:00

The most common convention seems to be to end in a *

seancorfield05:11:51

@qqq I've seen that in a lot of libraries -- and started following it myself.

gfredericks12:11:57

I have the uncommon preference for foo', imitating mathematical notation

guy13:11:56

Hi has anyone made a spec for a base64 encoded string before?

gfredericks13:11:19

that sounds like it could be a regex

guy13:11:36

thats a smart idea

gfredericks13:11:39

though perhaps not a trivial one if you want to really follow the spec

gfredericks13:11:15

but of course that's something somebody else has done somewhere, e.g. https://stackoverflow.com/questions/475074/regex-to-parse-or-validate-base64-data

guy13:11:32

yeah was just looking at that! thanks :thumbsup:

hlship23:11:17

I'm stumbling on something pretty basic. s/cat is not working the way I'd expect.

(s/conform ::field-def [:foo :text]) 
=> {:field-name :foo, :field-type :text}
(s/conform (s/cat :fd ::field-def) [:foo :text]) 
=> {:fd {:field-name :foo, :field-type :text}}
I would have expected that to fail; ::field-def is
(s/cat :field-name keyword?
                          :field-type field-types)
That is, my ::field-def expects a tuple of keyword and field-type (a set of keywords). So I'd expect s/cat to consume the first value from a list, then apply ::field-def as a predicate and deconstructor to it. Instead, it is applying ::field-def directly. From my (mis-?) understanding, I'd expect the following to succeed, but it fails:
(s/explain (s/cat :fd ::field-def) [[:foo :text]]) 
In: [0] val: [:foo :text] fails spec: :com.walmartlabs.genie.launchpad.db-access/field-def at: [:fd :field-name] predicate: keyword?
:clojure.spec.alpha/spec  {:clojure.spec.alpha/op :clojure.spec.alpha/pcat, :ps [:com.walmartlabs.genie.launchpad.db-access/field-def], :ret {}, :ks [:fd], :forms [:com.walmartlabs.genie.launchpad.db-access/field-def], :rep+ nil}
:clojure.spec.alpha/value  [[:foo :text]]
Again, my expectation is that s/cat consumes a seq. The first element in the seq should be a ::field-def, which itself is a seq of two elements. Instead, it is matching the treating the entire list [[:foo :text]] as the field-def tuple, and failing because the first value in the list, [:foo :text] is not a keyword.

hlship23:11:01

Basically, my goal is this:

(s/def ::primary-key (s/cat :pk-field-def ::field-def
                            :cluster-defs (s/* ::cluster-def)))
That is, a single field def, followed by zero or more cluster-def's.

seancorfield23:11:52

@hlship Regex specs "unwind" when they are combined, unless you wrap them in s/spec (or some other delimiting operation).

hlship23:11:41

Ok, that could be what I'm missing. It's right there in the docs, once I know what to look for!

seancorfield23:11:22

s/cat isn't meant for tuples -- there's s/tuple for that

seancorfield23:11:52

(although you'll get no labels with that I think...)

hlship23:11:37

Nice. I don't need the conformed value, I'm just validating.

seancorfield23:11:08

I think it catches everyone out at least once 🙂