malli 2025-03-04

Let's say I'm passing a delayed value between functions - is there a Malli type for that as an opaque box? What about a way to declare (even just for humans) what type the contents are?

IIUC the former could be delay?

Not sure I've seen a [:delay T] schema yet.

something like this might work

(defn -delay-schema []
  (m/-proxy-schema {:type :delay
                    :fn (fn [p c o]
                          (m/-check-children! :delay p c 1 1)
                          (let [c (mapv #(m/schema % o) c)]
                            [c (map m/form c) (m/schema delay? o)]))}))

I think it does both the things you want

Generator is something like:

(defmethod mg/-schema-generator :delay [schema options]
  (gen/fmap
    #(delay %)
    (mg/generator (first (m/children schema options)) options)))

Thanks for that, how would I go about calling it though, am I holding it wrong?

(require '[malli.core :as m])
  (require '[malli.registry :as mr])
  
  (defn -delay-schema []
    (m/-proxy-schema {:type :delay
                      :fn (fn [p c o]
                            (m/-check-children! :delay p c 1 1)
                            (let [c (mapv #(m/schema % o) c)]
                              [c (map m/form c) (m/schema delay? o)]))}))

  (binding [mr/*registry* {:string (m/-string-schema)
                           :delay (-delay-schema)}]
    (m/validate [:delay :string] (delay "x")))

;;=> 
  Unhandled clojure.lang.ExceptionInfo
   :malli.core/invalid-schema
   {:type :malli.core/invalid-schema,
    :message :malli.core/invalid-schema,
    :data {:schema :delay, :form [:delay :string]}}
                 core.cljc:  157  malli.core$_exception/invokeStatic
                 core.cljc:  157  malli.core$_exception/invoke
                   dev.clj:   18  malli.dev/-capture-fail!/fn/-fail!
            ...

try mr/set-default-registry! instead

the dynamic registry (supporting the *registry* binding is not enabled by default.

Thanks you guys

I am still hitting the same issue, though. Not sure what I am doing wrong, seems like this should work:

(require '[malli.registry])
  (require '[malli.core :as m])

  (defn -delay-schema [_]
    (m/-proxy-schema {:type :delay
                       :fn (fn [{:keys [force] :as p} c o]
                             (m/-check-children! :delay p c 1 1)
                             (let [c (mapv #(m/schema % o) c)
                                   v (m/-validator (first c))]
                               [c (map m/-form c) (m/schema [:fn (fn [d]
                                                                     (if (delay? d)
                                                                       (if (or (realized? d) force)
                                                                         (v @d)
                                                                         true)
                                                                       false))]
                                                              o)]))}))

  (malli.registry/set-default-registry! {:string (m/-string-schema)
                                         :delay (-delay-schema nil)})

  (m/validate :string "foo") ;; => true
  ;; (mc/validate :int "foo") ;; this throws, so I must be using the default registry

  (try (m/validate [:delay :string] (delay "foo"))
       (catch Exception e (ex-data e)))
;;=> {:type :malli.core/invalid-schema,
;;    :message :malli.core/invalid-schema,
;;    :data {:schema :fn, :form [:fn #function[user/-delay-schema/fn--201005/fn--201009]]}}

oh you need to add :fn to your registry

💯 1

for this prototype of :delay

👍 1

it's defined in terms of :fn for now via proxy-schema

should look more like -collection-schema in the ideal impl

That was it, thank you Ambrose

🎉 2

Of course, this is why it was failing with (m/schema delay? ...) before too!

oh, do you mean this was the original problem you were asking about, or trying the first impl?

Actually for the first one, I'm not sure how (mc/schema delay? o) could work without adding delay? somewhere

👍 1

Fleshed out :delay, :future, and :promise schemas https://github.com/metosin/malli/pull/1171

💪 1