malli

https://github.com/metosin/malli :malli:
Ben Sless 2021-05-04T06:24:06.201700Z

Next step is figuring out how to derive generators from this

Ben Sless 2021-05-04T07:14:53.202200Z

Most cases just work besides equality

Ben Sless 2021-05-04T08:28:33.202500Z

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)))

Ben Sless 2021-05-04T10:59:33.203400Z

I collected the proof of concept implementation with some explanations and cleaned up code at a repo https://github.com/bsless/malli-keys-relations

Ben Sless 2021-05-04T12:53:14.208100Z

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)

2021-05-04T13:46:24.209800Z

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

borkdude 2021-05-04T14:07:25.210500Z

Note that runtime resolve in general doesn't play well with GraalVM native-image unless it's executed at compile time

Ben Sless 2021-05-04T14:20:00.210800Z

I'll replace it with a map or defmulti

Ben Sless 2021-05-04T14:20:15.211100Z

I think defmulti will be best, extensible

Ben Sless 2021-05-04T15:28:21.213200Z

done

Ben Sless 2021-05-04T15:29:05.213600Z

What about the alternative syntax?