Fork me on GitHub

thanks all, i'll report back on how it goes!


@raymcdermott I can look your thing today/tomorrow.


@d.ian.b no inbuilt mapping for fn?. But, you can:

(m/validate [:fn fn?] (partial +))
; => true



  [:=> [:cat [:* [:int {:gen/min -1000, :gen/max 1000}]]] :int] 
  (partial +)
  {::m/function-checker mg/function-checker})
; => nil

Ian Fernandez11:03:18

I've made it right now haha

👍 1

  [:=> [:cat [:* [:int {:gen/min -1000, :gen/max 1000}]]] [:int {:min 1}]]
  (partial +)
  {::m/function-checker mg/function-checker})
;{:schema [:=> [:cat [:* [:int #:gen{:min -1000, :max 1000}]]] [:int {:min 1}]],
; :value #object[clojure.core$_PLUS_ 0x6edca2b1 "[email protected]"],
; :errors (#Error{:path [],
;                 :in [],
;                 :schema [:=> [:cat [:* [:int #:gen{:min -1000, :max 1000}]]] [:int {:min 1}]],
;                 :value #object[clojure.core$_PLUS_ 0x6edca2b1 "[email protected]"],
;                 :check {:total-nodes-visited 0,
;                         :depth 0,
;                         :pass? false,
;                         :result false,
;                         :result-data nil,
;                         :time-shrinking-ms 0,
;                         :smallest [()],
;                         :malli.generator/explain-output {:schema [:int {:min 1}],
;                                                          :value 0,
;                                                          :errors (#Error{:path [],
;                                                                          :in [],
;                                                                          :schema [:int {:min 1}],
;                                                                          :value 0})}}})}

clojure-spin 2
Ian Fernandez11:03:22

How I can use a register of the (m/function-schemas) registry, onto m/validate?

Ian Fernandez16:03:41

(get-in (m/function-schemas) [(quote *ns*) 'foo :schema])


@d.ian.b good question, atm, no easy way. Idea with the function registry is that there will be a instrument kinda thing, that will wrap a) some b) all registered function schmaas like Orchestra - running input & output validation. Could be also used to emit generated data based only on the function definitions. Ideas and PRs welcome on that.


also, did a spike on infferring schemas from normal vars. you get useful guesses pretty easily, better with tools.analyzer & clj-kondo and I guess. really good with core.typed.


the new kw-varargs thing would work nicely with global registry, my guess is that the core team will plug into that with spec. e.g. given a function:

(defn doit [& {:domain.user/keys [id name]}] [id name])
… running (m/collect #'doit) would infer a [:map :domain.user/id :domain.user/name] out of it, register it as a malli function schma, after (m/instrument my-registry) saying:
(doit :domain.user/id 1, :domain.user/name "kikka")
would cause it to run validation.

clojure-spin 1

given there is few hours extra time, I would write a sample code so that I could prove a point that it’s doable and awesome.

sheepy 1

I don't seem to be able to merge maps with [:and] constraints


(def x [:and [:map
              [:start int?]
              [:end int?]]
        [:fn (fn [{:keys [start end]}]
               (< start end))]])
=> #'user/x
(def y [:map
        [:here int?]
        [:there int?]])
=> #'user/y
(require '[malli.util :as mu])
=> nil
(mu/merge y x)
=> [:and [:map [:start int?] [:end int?]] [:fn #object[user$fn__4910 0x40fa91ef "[email protected]"]]]
(mu/merge x y)
=> [:map [:here int?] [:there int?]]


is this expected?


and should merge combine the predicate in another predicate which ands those if both maps have predicates?


it should invoke both functions ... maybe the order would not be predictable but I'll take that


probably the order of merge args


this could lead to funny problems, like what if you merge in a closed map in an open map, probably the resulting map should be open?


or should merge consider predicates and other properties like metadata, which is ignored in merge args?


(with-properties-of (merge x y) y)


merge takes the last as the 'winner' so I think that would be the most idiomatic


but I agree that merging things that are not maps is tricky


Plumatic dropped s/both in favour of s/constrained just because the first is not a good idea: “apple and fruit and a car” please. Currently :and already kinda means “the first thing constrained with the rest” as we pick the generator from first and then constraint with the rest using gen/such-that. Given that, we could make :and mergable, would merge with the first and keep the rest as extra leaves of :and? e.g.

[:map ::x]
[:map ::y] 
; => [:map ::x ::y]

[:map ::x]
[:and [:map ::y] map?] 
; => [:and [:map ::x ::y] map?]

[:and [:map ::x] map?]
[:map ::y] 
; => [:and [:map ::x ::y] map?]

[:and [:map ::x] map?]
[:and [:map ::y] map?] 
; => [:and [:map ::x ::y] map? map?]

[:and [:map ::x]]
; => map?
would that be … more correct?


having [:and [:map …] [:fn …]] is quite common, having it non-mergable is a bummer.

😬 1

if both maps have [:and [:map ..][fn...] it could be rejected. If one has an [:and ...] and the other doesn't can't you still merge the maps? I am probably under thinking it 🙂

Panel 300022:03:22

Anyway to have a dynamic default ? Like if I want a default timestamp to be generated when runing decode with default-value-transformer ?

Panel 300023:03:39

 [:map {:registry
        {:inst (m/-simple-schema
                {:type :inst
                 :pred inst?})}}
  [:time :inst]
  [:id1 :uuid]
  [:id2 :uuid]]
  {:defaults {:inst (constantly (rand-int 100))
              :uuid (constantly (char (rand-int 100)))}}))
Found something that works for me, but the default are generated once per type so for example if you need two different uuid it won't work.

Panel 300023:03:22

 [:map {:registry
        {:inst (m/-simple-schema
                {:type :inst
                 :pred inst?})}}
  [:time :inst]
  [:id :uuid]])
This throw a java.lang.StackOverflowError

Panel 300001:03:09

It does work if the registry is passed in the options map

  [:time :inst]
  [:id :uuid]]
   {:inst (m/-simple-schema
           {:type :inst
            :pred inst?})})})