(s/def ::params (s/or :string string?
:map map?))
(defn is-null? [val]
(or (empty? val)
(= "null" val)
(nil? val)))
(s/def ::non-null-params
(s/and ::params
#(not (is-null? %))))
(gen/sample (s/gen ::non-null-params))
Why does ::non-null-params still give me empty maps and empty strings?Because s/or produces a pair. Either [:string s] or [:map m]
is-null? could have [[_ val]] as its arglist and it will work.
Or you could test (is-null? (second %))
Ah ok. Then clearly I didn't want to use s/or I wanted to choose one or the other.
(technically it's a MapEntry so (val %) is "more correct" than (second %)
s/or is how you do it, but it returns a tagged pair to tell you which branch matched.
(s/def ::non-null-params
(s/and ::params
#(not (is-null? (val %)))))
Thanks Sean.
It's working just as expected!I think Alex has said that Spec 2 will have a non-conforming or that doesn't do that, or at least some easy way to avoid it...
"Will have", as in "when it's released", or "is being talked about". Can I test it now?
It's only available via git deps and it's kind of buggy.
Alright, maybe an adventure for another day.
What you can do with Spec 1 is used the undocumented nonconforming function, which is currently documented for Spec 2 (but might go away -- it will still be in Spec 1 tho'):
(s/def ::params (s/nonconforming (s/or :string string? :map map?)))
Spec 1 isn't going away. Spec 2 will most likely morph into the actual "core" Spec at some point and folks will either migrate from Spec 1 to "Spec" or use both side-by-side.
For a while at work, we maintained a branch of our code base migrated to use Spec 2, and help Alex test stuff, but it was such a moving target and several places were buggy and/or incomplete so after several months we abandoned trying to keep our branch updated and decided to wait for Spec 2 to mature.
Spec 2 has a lot of improvements over Spec 1 but it is also quite different in several places.
Either way, I'm excited to see how it turns out.