Search code examples
clojureclojure.spec

clojure.spec conform throws stack overflow exception


Can anybody explain, what's wrong with the example below? Why does it throw the StackOverflowError exception?

(s/def ::tag keyword?)
(s/def ::s string?)
(s/def ::n number?)
(s/def ::g
  (s/cat :tag (s/? ::tag)
         :ex (s/alt :string ::s
                   :number ::n
                   :and (s/+ ::g)
                   )))


(s/conform ::g '["abc"])

Solution

  • Similarly to what Alex Miller points out in this Google Groups discussion, s/+ tries to resolve ::g during the definition.

    This should do what you want, I think:

    (s/def ::g
           (s/spec (s/cat :tag (s/? ::tag)
                          :ex (s/alt :string ::s
                                     :number ::n
                                     :and ::g))))
    
    ; REPL
    user=> (s/conform ::g [:foo [:bar "abc"]])
    {:ex [:and {:ex [:string "abc"] :tag :bar}] :tag :foo}