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 is a website building & hosting documentation for Clojure/Script libraries
× close