clojure-spec

About: http://clojure.org/about/spec Guide: http://clojure.org/guides/spec API: https://clojure.github.io/spec.alpha/clojure.spec.alpha-api.html
konrad szydlo 2020-12-10T12:58:40.480500Z

Hi, I'm trying to figure out how to implement xor for a map keys. Where I'd like to check if one of the keys is present but not both at the same time.

(s/def ::a int?)
(s/def ::b int?)
(s/def ::c string?)
Where following maps are invalid: {::c "string"} ;; missing ::a xor ::b {::a 1 ::b 2 ::c "string"} ;; both ::a and ::b present and the following maps are valid: {::a 1 ::c "string"} {::b 2 ::c "string"}

vlaaad 2020-12-10T14:12:01.481200Z

(s/and (s/keys ...) #(= 2 (count (select-keys % [::a ::b ::c]))))?

english 2020-12-10T14:12:03.481300Z

s/keys only supports regular or: https://stackoverflow.com/a/41901585 but you could combine the s/keys spec with a custom xor spec via s/and, as described in https://stackoverflow.com/a/43374087

konrad szydlo 2020-12-10T14:45:55.481700Z

Thank you. My searching on duck duck go didn't return this answer from SO. That's what I was looking for. In the docs for s/keys I saw that or is supported but not xor