Thank you Alex.
It happens that I forgot to name the kwargs part in the s/cat call, so the working version should be :
(s/fdef adder
:args (s/cat :a integer? :b integer? :kwargs (s/keys* :opt-un [::c]))
:ret string?)
I'm asking because I've just discovered something about s/cat + s/or + s/keys* (after 1 day and a half of trials).
Before I added the keyword args spec, the specs of my function were like this (simplified) :
(s/fdef adder
:args (s/or :version1 (s/cat :a integer? :b integer?)
:version2 (s/cat :a number? :b number?)
:ret integer?))
This version is working just fine, with stest/check etc.
When I added keyword args spec yesterday, I added it like this :
(s/fdef adder
:args (s/cat :normal-args (s/or :version1 (s/cat :a integer? :b integer?)
:version2 (s/cat :a float? :b float?))
:kwargs (s/keys* :opt-un [::c]))
:ret number?)
It produced some strange behavior. Under `stest/check`, the arguments passed to the function were in a messed up form. The smallest input found by stest/check is `:smallest [((1.0 1.0))]` which looks like a sequence inside a sequence. When I finally realized that I couldn't "un-factorize" the spec of the keyword args and the put it into each s/or branch, it worked :
(s/fdef adder
:args (s/or :version1 (s/cat :a integer? :b integer? :kwargs (s/keys* :opt-un [::c]))
:version2 (s/cat :a float? :b float? :kwargs (s/keys* :opt-un [::c])))
:ret number?)
I realize that nesting s/cat calls can produce nested sequences, but in my case it seemed natural at first to factorize the spec of the keyword args and express the specificity of the "normal args" separately. It's like check couldn't somehow "unroll" the nested s/cat...
My question is: does it make sense ? Should it work and it's a bug ? Is there no way to factorize like I tried (I would be fine with this really).
I hope I made my question clear, it took me quite some time to nail it and create a reproduction case.