Next step is figuring out how to derive generators from this
Most cases just work besides equality
Here we go:
(defn- derive-from-fmap
[schema options gen]
(let [props (merge (m/type-properties schema)
(m/properties schema))]
(when-some [fmap (:gen/fmap props)]
(gen/fmap (m/eval fmap (or options (m/options schema)))
gen))))
(defmethod mg/-schema-generator :and [schema options]
(let [[h & t] (m/children schema options)
base-gen (mg/generator h options)
gen (reduce (fn [gen schema]
(if-let [gen (derive-from-fmap schema options gen)]
gen
gen))
base-gen
t)]
(gen/such-that (m/validator schema options) gen 100)))
I collected the proof of concept implementation with some explanations and cleaned up code at a repo https://github.com/bsless/malli-keys-relations
Some more thoughts:
• should references to paths inside maps be explicit rather than implicit? i.e. [:keys/> :x :y]
vs [:keys/> [:path :x] [:path :y]]
. The second syntax is more cumbersome but gives more freedom (`[:path :x :z]`) and facilitates more logic (see next points)
• Facts about collections. How do I say the value at key k1
must be contained in the collection in k2
, or a number smaller than the size of that collection? Stuff like [:contains? :x :y]
(the value at y is in x), or [:> [:count :x] :y]
(y is smaller than the count of x)
Very cool stuff! I was playing with adding support for cljs yesterday. (resolve sym)
(https://github.com/bsless/malli-keys-relations/blob/master/src/com/github/bsless/malli_keys_relations.clj#L112) is not allowed in cljs - I suspect converting this to a macro may get cljs support working.
In cljs resolve only allows a literal quoted symbol as an argument: https://cljs.github.io/api/cljs.core/resolve
Note that runtime resolve
in general doesn't play well with GraalVM native-image unless it's executed at compile time
I'll replace it with a map or defmulti
I think defmulti will be best, extensible
done
What about the alternative syntax?