Fork me on GitHub
#clojure-spec
<
2019-02-06
>
flyboarder03:02:20

So this is a spec error I ran into today and Im here thinking there must be a better way to get to the root of the problem

taylor03:02:50

what’s on line 28 in bootstrap/feature.clj? is that your project?

flyboarder03:02:28

(defn- feature-dispatch [[k v]] k)

taylor03:02:09

it’s probably the destructuring of the first arg, maybe a keyword is being passed as the first arg

flyboarder03:02:25

^ I was able to solve this the problem was (spec/explain-data ::feature-gate feature) when I needed (spec/explain-data ::feature-gate [feature])

borkdude20:02:36

@alexmiller do you plan to support this for spec-alpha2 as well? https://dev.clojure.org/jira/browse/CLJ-2060 I noticed it does not yet work in CLJS.

alexmiller20:02:53

should work, haven’t looked at why yet, but wasn’t intentionally broken

seancorfield21:02:30

FYI, I just ran out entire test suite against the latest spec2 and there's just one failure (for s/valid? on a large data structure for a very complex, nested spec) -- which was the unexplained failure I had before. The generator problems I mentioned before are fixed by the latest work.

seancorfield21:02:29

@alexmiller What in spec (or spec2) causes this predicate to be used? (or (nil? %) (sequential? %))

seancorfield21:02:57

(it's not in our code so I assume it's what underlies s/cat or something?)

alexmiller21:02:05

I think that’s checked for all regex specs

alexmiller21:02:54

I assume you see that fail?

seancorfield21:02:38

I've tracked it down a bit further...

(def s [ ... sequence of hash maps ...])
(count s) ;;=> 6
(s/explain ::ba-decline (take 3 s)) ;;=> Success!
(s/explain ::ba-decline (drop 3 s)) ;;=> Success!
(s/explain (s/cat :one ::ba-decline :two ::ba-decline) s)
;; fails, claiming that the first element of s does not satify: (or (nil? %) (sequential? %)) in: [0] at: [:one]

seancorfield21:02:18

(this works with spec1)

seancorfield21:02:00

Am I missing something obvious about combining regex specs?

seancorfield21:02:56

The ::ba-decline spec is an s/cat of three items.

seancorfield21:02:58

I'll see if I can create a minimal example that fails, based on this (unfortunately there are a lot of complex specs behind this).

seancorfield22:02:23

@alexmiller

(s/def ::x string?)
(s/def ::y int?)
(s/def ::z keyword?)
(s/def ::a (s/keys :req-un [::x]))
(s/def ::b (s/keys :req-un [::y]))
(s/def ::c (s/keys :req-un [::z]))
(s/def ::abc (s/cat :a ::a :b ::b :c ::c))
(def a {:x "x"})
(def b {:y 42})
(def c {:z :bar})
(s/explain ::abc [a b c])
(s/explain (s/cat :one ::abc :two ::abc) [a b c a b c])
works on spec1, fails on spec2

seancorfield22:02:42

on spec2 {:x "x"} - failed: (or (nil? %) (sequential? %)) in: [0] at: [:one]

alexmiller23:02:42

user=> (s/explain (s/cat :one ::abc :two ::abc) [[a b c] [a b c]])
Success!
certainly is suspicious :)

seancorfield23:02:17

It's almost like regex specs don't unroll anymore! :rolling_on_the_floor_laughing:

alexmiller23:02:43

I may have actually introduced that by introducing the delayed resolution of aliased specs

alexmiller23:02:07

basically regex specs in the registry are shielded by the keyword (which is not a regex spec), so the code doesn’t believe they can be combined

alexmiller23:02:05

so this may fight with the last changes - I can’t remember now if that was from forward references or from something about gens?

seancorfield23:02:55

This was broken before you fixed either of those I believe. Certainly broken before the gensub fix.

alexmiller23:02:30

well good to know then :)

seancorfield23:02:35

Although, with a quick clj -Sdeps ... it's enough to test that repro case against any version of spec2 🙂

bananadance 1
alexmiller22:02:42

I’ll take a look, seems buggy to me

alexmiller22:02:10

There is a lot gnarly code in that form/object transition. I could easily have broken something subtle

alexmiller22:02:33

Thanks for the repro

seancorfield22:02:52

I was lucky that the first simple repro I tried still broke 🙂

alexmiller22:02:13

Hey, that’s a good sign

seancorfield22:02:02

At this point, it really is a pretty minimal set of changes in our code to go from spec1 to spec2. It's frustrating that we can no longer use comp and partial to construct predicates and have to resort to #(..) or (fn [x] ..) but, fortunately, that didn't affect much code.

seancorfield22:02:05

We have a few places we're having to use s/spec* now so the "helper macros" mentioned in your latest journal will help clean that up when they drop in GitHub.

alexmiller22:02:10

yeah, that has further solidified today and I think will be very useful

borkdude22:02:58

I still have at least 3 bugs with spec alpha 2 (see issue link above)

seancorfield22:02:15

Interesting. I never knew you could define a spec to nil to make it go away...

borkdude22:02:05

It’s a fairly recent addition.

borkdude22:02:32

Make that 2. The (s/def spec nil) was a mistake on my part, I had to call unstrument first (which failed because ::s/invalid is not a valid any? which I ran into)

borkdude22:02:43

undefining still works:

$ clj -A:test
Clojure 1.10.0
user=>  (require '[clojure.spec-alpha2 :as s])
nil
user=> (require '[clojure.spec-alpha2.test :as stest])
nil
user=> (defn foo [x] x)
#'user/foo
user=> (s/fdef foo :args (s/cat :x number?) :ret number?)
user/foo
user=> (stest/instrument `foo)
[user/foo]
user=> (foo "a")
Execution error - invalid arguments to user/foo at (test.clj:129).
"a" - failed: number? at: [:x]
user=> (stest/unstrument)
[user/foo]
user=> (s/def foo nil)
user/foo
user=> (stest/instrument `foo)
[]