Fork me on GitHub
#malli
<
2021-10-25
>
Ben Sless09:10:04

how should I compile a transformer which I want to operate only on leave?

Ben Sless11:10:11

It's pretty terrible but it works. Anything here a bad idea?

(defn -strip-invalid-optional-keys-transformer
  [schema _]
  (let [entries (filter #(:optional (m/properties (second %))) (m/entries schema))
        fs (map (fn [[k v]]
                  (let [validator (m/validator v)]
                    (fn [m]
                      (if-let [e' (find m k)]
                        (let [v' (val e')]
                          (if (validator v')
                            m
                            (dissoc m k)))
                        m))))
                entries)]
    (reduce comp fs)))

(def strip-invalid-optional-keys-transformer
  (let [transform {:compile
                   (fn [schema _]
                     {:leave -strip-invalid-optional-keys-transformer})}
        encoders {:map transform}]
    (mt/transformer
     {:decoders encoders
      :encoders encoders})))

ikitommi16:10:09

with a quick look, looks good. the runtime is bare minimum, everything possible has been pushed to creation time.

ikitommi16:10:23

but, should the encoding happen at enter?

ikitommi16:10:07

e.g. you have valid value, after encoding, the keys could be different, (e.g. stringified) so the transforming functions misses all the keys.

Ben Sless18:10:58

you're correct, I didn't consider the encode case

Ben Sless18:10:21

I must say the order where things happen with regards to transformers compilation was very hard to follow 😞

Ben Sless11:10:11

It's pretty terrible but it works. Anything here a bad idea?

(defn -strip-invalid-optional-keys-transformer
  [schema _]
  (let [entries (filter #(:optional (m/properties (second %))) (m/entries schema))
        fs (map (fn [[k v]]
                  (let [validator (m/validator v)]
                    (fn [m]
                      (if-let [e' (find m k)]
                        (let [v' (val e')]
                          (if (validator v')
                            m
                            (dissoc m k)))
                        m))))
                entries)]
    (reduce comp fs)))

(def strip-invalid-optional-keys-transformer
  (let [transform {:compile
                   (fn [schema _]
                     {:leave -strip-invalid-optional-keys-transformer})}
        encoders {:map transform}]
    (mt/transformer
     {:decoders encoders
      :encoders encoders})))

Ben Sless15:10:06

It seems that most times where relations about map keys are requires by users it is to specify mutual exclusion. Could it be worth it to add a mutex property which takes a collection of keys which are mutually exclusive?

ikitommi16:10:59

woudn’t the key-relations solve that? havan’t had time to give that much though, but agree something should be there in the core.

Ben Sless18:10:08

Getting the key-relations to work correctly and with good performance will be lots of work which I don't know when I'll get to. Adding :mutex [[:a :b]] can be done in a couple of hours