This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2022-08-23
Channels
- # babashka (104)
- # beginners (23)
- # calva (15)
- # cider (2)
- # clojure (29)
- # clojure-europe (14)
- # clojure-nl (2)
- # clojure-norway (3)
- # clojure-spec (4)
- # clojure-switzerland (1)
- # cursive (3)
- # datomic (6)
- # emacs (17)
- # etaoin (2)
- # expound (1)
- # fulcro (4)
- # graphql (4)
- # honeysql (7)
- # introduce-yourself (2)
- # jackdaw (5)
- # malli (3)
- # meander (19)
- # nbb (3)
- # off-topic (35)
- # pathom (6)
- # pedestal (4)
- # polylith (31)
- # rdf (11)
- # re-frame (8)
- # reitit (6)
- # shadow-cljs (8)
- # specter (4)
- # squint (15)
- # vim (6)
Does something like that make sense?
(defmulti dispatch identity)
(defmethod dispatch :default [v]
(:spec v))
(s/valid?
(s/multi-spec dispatch :spec)
{:spec (s/keys :req-un [::a ::b]) :a 1 :b 2})
=> true
The real code in :default
branch would be more complex, but the idea is that I have a complex rule to infer spec from the value, and I don't want to encode it in a single predicate that executes the rule and calls s/valid?
inside because it will lose the error reporting/explanation. I.e. I don't want to do this:
(s/valid?
(s/spec #(s/valid? (:spec %) %))
{:spec (s/keys :req-un [::a ::b]) :a 1})
=> false
because (s/explain-data ...)
will just say that (s/valid? (:spec %) %)
is false and not that the :b
is missingExplanation comparison:
(s/explain
(s/spec #(s/valid? (:spec %) %))
{:spec (s/keys :req-un [::a ::b]) :a 1})
=> {:spec ... :a 1} - failed: (valid? (:spec %) %)
(s/explain
(s/multi-spec dispatch :spec)
{:spec (s/keys :req-un [::a ::b]) :a 1})
=> {:spec ... :a 1} - failed: (contains? % :b)
check this out:
(defmacro def-dynamic-spec [name & fn-tail]
(let [multi-name (symbol (str name "-multi-fn"))]
`(do
(defmulti ~multi-name (constantly nil))
(defmethod ~multi-name nil ~@fn-tail)
(def ~name (s/multi-spec ~multi-name nil)))))
a macro that creates a spec that dynamically infers a value spec using a function of the value, while preserving error reporting/explanation data