The s/or spec conforms to [flag value] – where flag is the name given in s/or to the spec that matches (to produce the value). s/and flows the conformed result of the first spec into the remaining specs, so ::testcc is being passed a vector with two elements instead of the map you are trying to conform.
You can either add (s/conformer second) so that the conformed s/or result is unpacked (to get just the value) or you can wrap the ::test spec in a call to the (undocumented) s/nonconforming function which returns the original, rather than the conformed value: (s/and ::test (s/conformer second) ::testcc) (s/and (s/nonconforming ::test) ::testcc) Sean Corfield -- (970) FOR-SEAN -- (904) 302-SEAN An Architect's View -- http://corfield.org/ "If you're not annoying somebody, you're not really alive." -- Margaret Atwood ________________________________ From: [email protected] <[email protected]> on behalf of Philipp Neumann <[email protected]> Sent: Monday, May 28, 2018 10:00:22 AM To: Clojure Subject: Clojure Spec question with and/or composition Hi. I hope this is the right place for Spec questions. I try to composite different specs with and/or (I tried Google, but searching for and/or is useless :/): (s/def ::testa #{"a"}) (s/def ::testb #{"b"}) ;;;(sdef+ ::testaa {:a ::testa}) (do (clojure.spec.alpha/def :data$testaa/a :data/testa) (clojure.spec.alpha/def :data/testaa (clojure.spec.alpha/keys :req-un (:data$testaa/a)))) ;;;(sdef+ ::testbb {:b ::testb}) (do (clojure.spec.alpha/def :data$testbb/b :data/testb) (clojure.spec.alpha/def :data/testbb (clojure.spec.alpha/keys :req-un (:data$testbb/b)))) ;;;(sdef+ ::testcc {:c ::testb}) (do (clojure.spec.alpha/def :data$testcc/c :data/testb) (clojure.spec.alpha/def :data/testcc (clojure.spec.alpha/keys :req-un (:data$testcc/c)))) (s/def ::test (s/or ::testaa ::testaa ::testbb ::testbb)) (s/def ::test2 (s/and ::test ::testcc)) (s/describe ::test2) (s/conform ::test {:b "b" :c "b"}) ;[:data/testbb {:b "b", :c "b"}] (s/conform ::testcc {:b "b" :c "b"}) ;{:b "b", :c "b"} (s/explain ::test2 {:b "b" :c "b"}) {:b "b" :c "b"} is valid? for ::test and ::testcc, but not for the combination of them with (s/and ::test ::testcc). I did all the intermediate specs, to decouple the specs with map-keywords without namespaces (I wanted the spec to work with legacy maps). I obviously do something wrong, but I don't know how to improve on this. Kind Regards -- You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to [email protected] Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to [email protected] For more options, visit this group at http://groups.google.com/group/clojure?hl=en --- You received this message because you are subscribed to the Google Groups "Clojure" group. To unsubscribe from this group and stop receiving emails from it, send an email to [email protected]<mailto:[email protected]>. For more options, visit https://groups.google.com/d/optout. -- You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to [email protected] Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to [email protected] For more options, visit this group at http://groups.google.com/group/clojure?hl=en --- You received this message because you are subscribed to the Google Groups "Clojure" group. To unsubscribe from this group and stop receiving emails from it, send an email to [email protected]. For more options, visit https://groups.google.com/d/optout.
