malli

escherize 2025-03-04T17:43:56.353429Z

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?

2025-03-04T17:47:00.851379Z

IIUC the former could be delay?

2025-03-04T17:47:40.942419Z

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

2025-03-04T17:50:35.027059Z

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)]))}))

2025-03-04T17:51:22.732139Z

I think it does both the things you want

2025-03-04T18:08:32.924459Z

Generator is something like:

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

escherize 2025-03-04T18:34:41.355909Z

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!
            ...

ikitommi 2025-03-04T20:15:48.652679Z

try mr/set-default-registry! instead

ikitommi 2025-03-04T20:16:42.755509Z

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

2025-03-04T20:19:47.709029Z

fwiw I fleshed it out a bit here https://github.com/metosin/malli/pull/1171

escherize 2025-03-04T20:24:20.556339Z

Thanks you guys

escherize 2025-03-04T20:37:33.529309Z

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]]}}

2025-03-04T20:39:21.244899Z

oh you need to add :fn to your registry

💯 1
2025-03-04T20:39:33.876619Z

for this prototype of :delay

👍 1
2025-03-04T20:40:21.057609Z

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

2025-03-04T20:40:41.673679Z

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

escherize 2025-03-04T20:41:19.529779Z

That was it, thank you Ambrose

🎉 2
escherize 2025-03-04T20:44:41.143329Z

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

2025-03-04T20:44:57.567249Z

ha glad you asked

2025-03-04T20:45:48.221929Z

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

escherize 2025-03-04T20:48:17.553859Z

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

👍 1
2025-03-09T00:31:17.059919Z

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

💪 1