Comment made by: pangloss
Playing around in the REPL today, I came up with this code that seems to work well converting arbitrary literals into generators:
`
(defprotocol LiteralGenerator
(-literal->generator [literal]))
(defn literal->generator [literal]
(cond
(satisfies? LiteralGenerator literal) (-literal->generator literal)
(vector? literal) (apply gen/tuple (mapv literal->generator literal))
(and (map? literal) (= [:gen] (keys literal)) (fn? (:gen literal))) literal
(map? literal) (gen/fmap (partial into {}) (literal->generator (mapv vec literal)))
(set? literal) (gen/fmap set (literal->generator (vec literal)))
(list? literal) (gen/fmap (partial apply list) (literal->generator (vec literal)))
:else (gen/return literal)))
`
Generating from a record is probably something that would be generally useful, so I added this as well:
`
(defn record->generator
([record]
; Is there a better way to do this?
(let [ctor (eval (read-string (str "map->" (last (clojure.string/split (str (class record)) #"\.")))))]
(record->generator ctor record)))
([ctor record]
(gen/fmap ctor (literal->generator (into {} record)))))
`
Which enables me to extend a record like this:
(defrecord Foo [a b]
LiteralGenerator
(-literal->generator [this] (record->generator map->AbcDef this)))
I haven't looked at the possibility of baking this code into test.check at all yet. I'd like feedback on what I've got so far before pursuing this any further.