Share your thoughts in the 2024 State of Clojure Survey!

Welcome! Please see the About page for a little more info on how this works.

0 votes
in Spec by

It seems like if ::my-spec validates, then (s/and ::my-spec ::my-spec) should also validate.

This is a simplified version of my actual code, but I'm running into problems validating some data that is spec'd using a combination s/and, s/keys, and s/or. This is the smallest reproduction I could come up with.

(s/def :a/coordinate
  (s/or :double double?
        :int int?))
(s/valid?
 (s/keys)
 {:a/coordinate 1.0})
;; true

(s/valid?
 (s/and (s/keys))
 {:a/coordinate 1.0})
;; true

(s/valid?
 (s/and (s/keys)
        (s/keys))
 {:a/coordinate 1.0})
;; false

(s/explain-str
 (s/and (s/keys)
        (s/keys))
 {:a/coordinate 1.0})
;; "[:double 1.0] - failed: double? in: [:a/coordinate] at: [:a/coordinate :double] spec: :a/coordinate\n[:double 1.0] - failed: int? in: [:a/coordinate] at: [:a/coordinate :int] spec: :a/coordinate\n"

1 Answer

+1 vote
by
selected by
 
Best answer

s/and flows the conformed result through the s/and specs, so if the conformed result is different (often due to s/or, s/cat, s/alt) then this will not necessarily work.

If you want to avoid conforming the s/or to a different value, you can wrap that spec in s/nonconforming.

...