Creating from recursive definitions using the Clojure Spec

Let's take a look at a Clojure Spec regexp for hiccup syntax

(require '[clojure.spec :as spec])

(spec/def ::hiccup
  (spec/cat :tag        keyword?
            :attributes (spec/? map?)
            :content    (spec/* (spec/or :terminal string?
                                         :element  ::hiccup))))

which works great

(spec/conform ::hiccup [:div#app [:h5 {:id "loading-message"} "Connecting..."]])
; => {:tag :div#app, :content [[:element {:tag :h5, :attributes {:id "loading-message"}, :content [[:terminal "Connecting..."]]}]]}

until you try to generate some example data for your functions from the specification

(require '[clojure.spec.gen :as gen])
(gen/generate (spec/gen ::hiccup))
; No return value but:
; 1. Unhandled java.lang.OutOfMemoryError
;    GC overhead limit exceeded

Is there a way to rewrite the specification so that it creates a working generator? Or do we need to attach some simplified generator to the specification?

+4
source share
1 answer

spec/*recursion-limit* ( 4) - , . , spec impls (* or), - (, map? ). , , .

( ) :

(binding [spec/*recursion-limit* 1] (gen/generate (spec/gen ::hiccup)))

, - * map?. . , ( map-of :gen-max).

+3
source

Source: https://habr.com/ru/post/1675330/


All Articles