Whether validate-input and validate-output should validate things or not.
Whether [[validate-input]] and [[validate-output]] should validate things or not.
(deparameterized-fn-form parsed & [fn-name])Impl for macaw.util.malli.fn/fn and macaw.util.malli.defn/defn. Given a parsed fn tail (as parsed
by [[parsed-fn-tail]]), return a [[clojure.core.fn]] form with the parameters stripped out.
(deparameterized-fn-form (parse-fn-tail '[:- :int [x :- :int] (inc x)])) ;; => (fn [x] (inc x))
Impl for [[macaw.util.malli.fn/fn]] and [[macaw.util.malli.defn/defn]]. Given a parsed `fn` tail (as parsed by [[parsed-fn-tail]]), return a [[clojure.core.fn]] form with the parameters stripped out. (deparameterized-fn-form (parse-fn-tail '[:- :int [x :- :int] (inc x)])) ;; => (fn [x] (inc x))
(deparameterized-fn-tail {[arities-type arities-value] :arities :as _parsed})Generate a deparameterized fn tail (the contents of a fn form after the fn symbol).
Generate a deparameterized `fn` tail (the contents of a `fn` form after the `fn` symbol).
(fixup-stacktrace e)If exception is thrown from the [[validate]] machinery, remove those stack trace elements so the top of the stack is the calling function.
If exception is thrown from the [[validate]] machinery, remove those stack trace elements so the top of the stack is the calling function.
(fn & fn-tail)Malli version of [[schema.core/fn]].
Unless it's in a skipped namespace during prod, a form like:
(fn :- :int [x :- :int] (inc x))
compiles to something like
(let [&f (fn [x] (inc x))] (fn [a] (validate-input {} :int a) (validate-output {} :int (&f a))))
The map arg here is additional error context; for something like macaw.util.malli/defn, it will be something
like
{:fn-name 'metabase.lib.field/resolve-field-id}
If compiled in a namespace in [[namespaces-toskip]], during config/is-prod?, it will be emitted as a vanilla
clojure.core/fn form.
Known issue: this version of fn does not capture the optional function name and make it available, e.g. you can't
do
(mu/fn my-fn ([x] (my-fn x 1)) ([x y :- :int] (+ x y)))
If we were to include my-fn in the uninstrumented fn form, then it would bypass schema checks when you call
another arity:
(let [&f (fn my-fn ([x] (my-fn x 1)) ([x y] (+ x y)))] (fn ([a] (&f a)) ([a b] (validate-input {} :int b) (&f a b))))
;; skips the :- :int check on y in the 2-arity
(my-fn 1.0) ;; => 2.0
Since this is a big gotcha, we are currently not including the optional function name my-fn in the generated
output. We can probably fix this with [[letfn]], since it allows mutually recursive function calls, but that's a
problem for another day. The passed function name comes back from [[mc/parse]] as :name if we want to attempt to
fix this later.
Malli version of [[schema.core/fn]].
Unless it's in a skipped namespace during prod, a form like:
(fn :- :int [x :- :int] (inc x))
compiles to something like
(let [&f (fn [x] (inc x))]
(fn [a]
(validate-input {} :int a)
(validate-output {} :int (&f a))))
The map arg here is additional error context; for something like [[macaw.util.malli/defn]], it will be something
like
{:fn-name 'metabase.lib.field/resolve-field-id}
If compiled in a namespace in [[namespaces-toskip]], during `config/is-prod?`, it will be emitted as a vanilla
clojure.core/fn form.
Known issue: this version of `fn` does not capture the optional function name and make it available, e.g. you can't
do
(mu/fn my-fn
([x] (my-fn x 1))
([x y :- :int] (+ x y)))
If we were to include `my-fn` in the uninstrumented `fn` form, then it would bypass schema checks when you call
another arity:
(let [&f (fn my-fn
([x] (my-fn x 1))
([x y] (+ x y)))]
(fn
([a]
(&f a))
([a b]
(validate-input {} :int b)
(&f a b))))
;; skips the `:- :int` check on `y` in the 2-arity
(my-fn 1.0) ;; => 2.0
Since this is a big gotcha, we are currently not including the optional function name `my-fn` in the generated
output. We can probably fix this with [[letfn]], since it allows mutually recursive function calls, but that's a
problem for another day. The passed function name comes back from [[mc/parse]] as `:name` if we want to attempt to
fix this later.(fn-schema parsed)(fn-schema parsed options)Implementation for fn and macaw.util.malli.defn/defn. Given an unparsed parametered fn tail, extract the
annotations and return a :=> or :function schema.
options can contain :target which is either
:target/metadata: generate the schema to attach to the metadata for a macaw.util.malli.defn/defn. For
key-value varargs like & {:as kvs} get a schema like [:* :any] in this case since the args aren't parsed to a
map yet
:target/instrumentation: generate a schema for use in generating the instrumented fn form. & {:as kvs} can
have a real map schema here.
Implementation for [[fn]] and [[macaw.util.malli.defn/defn]]. Given an unparsed parametered fn tail, extract the
annotations and return a `:=>` or `:function` schema.
`options` can contain `:target` which is either
* `:target/metadata`: generate the schema to attach to the metadata for a [[macaw.util.malli.defn/defn]]. For
key-value varargs like `& {:as kvs}` get a schema like `[:* :any]` in this case since the args aren't parsed to a
map yet
* `:target/instrumentation`: generate a schema for use in generating the instrumented `fn` form. `& {:as kvs}` can
have a real map schema here.(instrument-ns? namespace)Returns true if mu.fn/fn and mu/defn in a namespace should be instrumented with malli schema validation.
Returns true if mu.fn/fn and mu/defn in a namespace should be instrumented with malli schema validation.
(instrumented-fn-form error-context parsed & [fn-name])Given a fn-tail like
([x :- :int y] (+ 1 2))
and parsed by [[parsed-fn-tail]],
return an unevaluated instrumented fn form like
(mc/-instrument {:schema [:=> [:cat :int :any] :any]} (fn [x y] (+ 1 2)))
Given a `fn-tail` like
([x :- :int y] (+ 1 2))
and parsed by [[parsed-fn-tail]],
return an unevaluated instrumented [[fn]] form like
(mc/-instrument {:schema [:=> [:cat :int :any] :any]}
(fn [x y] (+ 1 2)))(parse-fn-tail fn-tail)Parse a parameterized fn tail with the [[SchematizedParams]] schema. Throw an exception if it cannot be parsed.
Parse a parameterized `fn` tail with the [[SchematizedParams]] schema. Throw an exception if it cannot be parsed.
(validate-input error-context schema value)Impl for macaw.util.malli.fn/fn; validates an input argument with value against schema using a cached
explainer and throws an exception if the check fails.
Impl for [[macaw.util.malli.fn/fn]]; validates an input argument with `value` against `schema` using a cached explainer and throws an exception if the check fails.
(validate-output error-context schema value)Impl for macaw.util.malli.fn/fn; validates function output value against schema using a cached explainer
and throws an exception if the check fails. Returns validated value.
Impl for [[macaw.util.malli.fn/fn]]; validates function output `value` against `schema` using a cached explainer and throws an exception if the check fails. Returns validated value.
cljdoc builds & hosts documentation for Clojure/Script libraries
| Ctrl+k | Jump to recent docs |
| ← | Move to previous article |
| → | Move to next article |
| Ctrl+/ | Jump to the search field |