Lambder
Lambder

Reputation: 2993

How to define Clojure spec for `'(foo (:x 1 :y 2))`

The:

(s/def ::a (s/cat :k keyword? :i int?))
(s/def ::b (s/cat :symbol any?
                  :a      (s/coll-of ::a)))

specs: (s/conform ::b '(foo ((:x 1) (:y 2))))

The:

(s/def ::a (s/cat :k keyword? :i int?))
(s/def ::b (s/cat :symbol any?
                  :a      (s/* ::a)))

specs: (s/conform ::b '(foo :x 1 :y 2))

but how do I spec (s/conform ::b '(foo (:x 1 :y 2))) ?

Upvotes: 0

Views: 85

Answers (1)

cfrick
cfrick

Reputation: 37063

To nest that into a list, you need to wrap it in s/spec. E.g.:

(s/def ::b (s/cat :symbol any? :a (s/spec (s/* ::a))))

This is mentioned in the Spec Guide:

When regex ops are combined, they describe a single sequence. If you need to spec a nested sequential collection, you must use an explicit call to spec to start a new nested regex context. For example to describe a sequence like [:names ["a" "b"] :nums [1 2 3]], you need nested regular expressions to describe the inner sequential data:

 (s/def ::nested
   (s/cat :names-kw #{:names}
          :names (s/spec (s/* string?))
          :nums-kw #{:nums}
          :nums (s/spec (s/* number?))))
 (s/conform ::nested [:names ["a" "b"] :nums [1 2 3]])
 ;;=> {:names-kw :names, :names ["a" "b"], :nums-kw :nums, :nums [1 2 3]}

Upvotes: 2

Related Questions