clojure-spec 2023-11-08

I have a case where conform returns :clojure.spec.alpha/invalid, but explain returns “Success!“. Am I missing something?

(def test-data (rest '(defn F "s||C_)C^?" {} ([[& {:keys [], :strs [a2p*1.+lNz3+9.-fc? !2_!T2*8_.aw7.H14*7 B_-T*E5+3lKy-gE Ca++-F*_G58!7+? VM.3-E**S*R+09eW f-F?J-D_?r*xdjb.D]} :as kQ.zi] & yeok5+8+3_O_.mXJZ] "MyN-Rmu[Y" nil :Wd--IU9M*! ":*ULe,h" :p-:?6+__S- J91*) "EcO")))
=> #'cursive.extensions.specs/test-data
(s/conform :clojure.core.specs.alpha/defn-args test-data)
=> :clojure.spec.alpha/invalid
(s/explain :clojure.core.specs.alpha/defn-args test-data)
Success!

Yeah that looks similar.

I’ve also found that generating code samples using the core specs doesn’t work well - it does work sometimes but not others, and I’m not sure why:

(gen/sample (s/gen ::core/bindings))
Error printing return value (ExceptionInfo) at clojure.test.check.generators/fn (generators.cljc:435).
Couldn't satisfy such-that predicate after 100 tries.

I’ve commented on the ask with some cases. Looks to me like the cases should be valid, so perhaps the bug is in conform.

The way s/and composes for generators is unlikely to get you a working generator for more complex specs, basically it takes the generator first spec, and then uses the rest of the specs in the and as a predicate to filter out generated values that don't match the entire s/and

It is limited to 100 tries

Hmm, I see. Thanks for the explanation.

I think there might be something you can bind to increase such-that's limit, but in general if you hit it you usually need to write a custom generator instead of relying on s/and's composed one

Is there a good way to figure out which spec is problematic? And can I override generators for the built-in specs?

The stacktrace didn’t seem especially useful.

spec has a way to define specs with custom generators, which is helpful for your own specs, for existing specs I sort of recall some mechanism for overriding but I am not sure

as far as figuring out which spec, I don't know

Ok, thanks. I’m currently generating these forms with my own code, and then just checking the result against the spec.