Fork me on GitHub
#malli
<
2021-08-04
>
Ben Sless09:08:03

I managed to narrow it down to multi-schemas

šŸ‘ 2
Ben Sless09:08:01

Specifically, the last bit

Ben Sless09:08:16

(let [schema [:multi {:dispatch first}
                  [:human [:cat [:= :human]]]
                  [:bear [:cat [:= :bear] [:* :int]]]
                  [::m/default [:tuple :string :string]]]]

      (testing "validate"
        (is (m/validate schema [:human]))
        (is (m/validate schema [:bear 1 2 3]))
        (is (m/validate schema ["defaultit" "toimii"]))
        (is (not (m/validate schema [:so :invalid]))))

      (testing "explain"
        (is (not (m/explain schema [:human])))
        (is (not (m/explain schema [:bear 1 2 3])))
        (is (not (m/explain schema ["defaultit" "toimii"])))
        (is (results= {:schema schema,
                       :value [:so :invalid],
                       :errors [{:path [::m/default 0], :in [0], :schema :string, :value :so}
                                {:path [::m/default 1], :in [1], :schema :string, :value :invalid}]}
                      (m/explain schema [:so :invalid]))))

      (testing "parser"
        (is (= (miu/-tagged :human [:human]) (m/parse schema [:human])))
        (is (= (miu/-tagged :bear [:bear [1 2 3]]) (m/parse schema [:bear 1 2 3])))
        (is (= (miu/-tagged ::m/default ["defaultit" "toimii"]) (m/parse schema ["defaultit" "toimii"])))
        (is (= ::m/invalid (m/parse schema [:so :invalid])))))

Ben Sless09:08:26

Something here is very wrong

Ben Sless09:08:15

Even more specifically, it's the parser

greg09:08:54

I've been using REBL recently and I noticed that Malli schemas are printed as regular one line strings, which is annoying. Although I found it is possible to provide custom viewer to REBL. Example:

(defn schema? [s]
  (m/schema? (try (m/schema s) (catch Exception _))))

(defn setup-rebl-viewers []
  (require '[cognitect.rebl])
  (cognitect.rebl/update-viewers
   {:malli/schema {:pred #'schema?
                   :ctor (fn [v]
                           (-> (m/form (m/schema v))
                               (fipp.edn/pprint {:width 80})
                               (with-out-str)
                               (cognitect.rebl.renderers/string-code-viewer)))}}))
#_(setup-rebl-viewers)
This is just a simple pretty print, but we could apply other strategies for formatting. If you have an idea what's the best way of formatting Malli schemas, please let me know in the comment.

Ben Sless09:08:59

Extend datafy to schemas and return form?

greg10:08:14

Hmm, I'll give it a try later :thinking_face:

greg10:08:42

Do you datafy malli schemas? Could you post an example?

Ben Sless10:08:03

Bit of black magic:

(require '[clojure.core.protocols :as p]
         '[malli.core :as m])


(extend-protocol p/Datafiable
  Object
  (datafy [x]
    (cond
      (satisfies? m/Schema x)
      (do
        (extend-protocol p/Datafiable
          (class x)
          (datafy [y] (m/-form y)))
        (p/datafy x))

      (satisfies? m/IntoSchema x)
      (do
        (extend-protocol p/Datafiable
          (class x)
          (datafy [y] (m/-form (m/schema y))))
        (p/datafy x))

      :else x)))

greg13:08:44

I think it could be simplified to

(extend-protocol p/Datafiable
  Object
  (datafy [x]
    (cond
      (satisfies? m/Schema x) (p/datafy (m/form x))
      (satisfies? m/IntoSchema x) (p/datafy (m/form (m/schema x)))
      :else x)))
Still as I mentioned in the other post (https://clojurians.slack.com/archives/C03S1KBA2/p1628084493261600?thread_ts=1628082589.258900&amp;cid=C03S1KBA2), I've got a feeling extending Object is not a good idea šŸ˜¬

emccue01:08:25

or, add some metadata to your schemas that extends the protocol

emccue01:08:42

thats probably the best way

emccue01:08:26

(with-meta [:map [:x int?]] ^{`p/datafy (fn [this] (p/datafy (m/form this)))})

šŸ‘ 2
greg22:08:40

Thanks for posting example. Still I think that would be yet another extreme if I add my own m/schema to keep it everywhere...

greg22:08:15

Actually, maybe this should be added to Malli itself, to m/schema :thinking_face: What do you think @U055NJ5CC about making Malli schemas datafy-able? (it is just an idea, I'm not sure is it good or bad, i'm just trying to figure out best practices of using these new protocols for my own and in this very thread it stroke me Malli could be a good place to define that datafy behaviour)

danielneal09:08:04

Iā€™m trying to make a recursive schema

danielneal09:08:10

doing something like this (simplified)

danielneal09:08:14

(malli/validate 
  [:vector {:registry {::property
                       [:map
                        [:property/type keyword?]
                        [:property/group {:optional true}
                         [:vector ::property]]]}}
   ::property]
  [{:property/type :string}
   {:property/type :key}])

danielneal09:08:20

but I get a stackoverflowerror

danielneal09:08:13

Iā€™m not sure model this kind of thing correctly

danielneal09:08:19

oh I see it, i need :ref ?