Fork me on GitHub
#malli
<
2020-07-02
>
katox08:07:41

@jkent of course, a shorter key than variants I tried. Thank you, it works!

ikitommi10:07:34

Almost there:

(def Order
  [:schema
   {:registry {"Country" [:map
                          [:name [:enum :FI :PO]]
                          [:neighbors [:vector  [:ref "Country"]]]]
               "Burger" [:map
                         [:name string?]
                         [:description {:optional true} string?]
                         [:origin [:maybe "Country"]]
                         [:price pos-int?]]
               "OrderLine" [:map
                            [:burger "Burger"]
                            [:amount int?]]
               "Order" [:map
                        [:lines [:vector "OrderLine"]]
                        [:delivery [:map
                                    [:delivered boolean?]
                                    [:address [:map
                                               [:street string?]
                                               [:zip int?]
                                               [:country "Country"]]]]]]}}
   "Order"])

(malli.mermaid/class-diagram Order)
; classDiagram
;   class Country {
;     :name [:enum :FI :PO]
;     :neighbors [:vector #:gen{:max 0} [:ref Country]]
;   }
;   class Burger {
;     :name string?
;     :description string?
;     :origin [:maybe Country]
;     :price pos-int?
;   }
;   class OrderLine {
;     :burger Burger
;     :amount int?
;   }
;   class Order {
;     :lines [:vector OrderLine]
;     :delivery Order_Delivery
;   }
;   class Order_Delivery_Address {
;     :street string?
;     :zip int?
;     :country Country
;   }
;   class Order_Delivery {
;     :delivered boolean?
;     :address Order_Delivery_Address
;   }
;   Country o-- Country
;   Burger o-- Country
;   OrderLine o-- Burger
;   Order o-- OrderLine
;   Order *-- Order_Delivery
;   Order_Delivery_Address o-- Country
;   Order_Delivery *-- Order_Delivery_Address

ikitommi10:07:20

as the map keys can be anything, the registry keys can be any non-vector. Strings looks nice.

ikitommi10:07:27

when a Schema is created (using m/schema), all the registry refs are eagerly validated and the current values are captured: • have an Invalid ref? -> fail early • using mutable registry? -> the created schema instance (including refs!) is still immutable • wan’t to know the local registry which the schema was created with -> accessible via m/options

ikitommi11:07:10

clojure.spec with mutable global registry, fail late and mutable refs doesn’t seem that right anymore.

Kevin19:07:45

Is this intended behavior? Here we say that the :id field is optional in the map schema. Which works

(m/validate
 [:map
  [:id {:optional true} int?]]
 {}) ; => true
Here we give the :id field a default value. But this doesn't work
(m/decode
 [:map
  [:id {:default 42} int?]]
 {}
 mt/default-value-transformer) ; => {}
Instead, we have to give field's spec a default, not the map's key
(m/decode
 [:map
  [:id [:and {:default 42} int?]]]
 {}
 mt/default-value-transformer) ; => {:id 42}
Personally I find the last example a bit strange (Or better yet, I find it strange that the second doesn't work). I'm not saying the ints have a default, I'm saying that this maps :id field has a default. Just like how :id is an optional field, not that that int? is an optional schema. Maybe there's a reason it's designed this way? I could just be looking at this from the wrong angle.

Kevin19:07:31

I guess it's more that I find it very unexpected that the second example doesn't work