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.
see https://github.com/metosin/malli?tab=readme-ov-file#registry-implementations
fwiw I fleshed it out a bit here https://github.com/metosin/malli/pull/1171
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
for this prototype of :delay
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
Of course, this is why it was failing with (m/schema delay? ...) before too!
ha glad you asked
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
Fleshed out :delay, :future, and :promise schemas https://github.com/metosin/malli/pull/1171