plumbing.fnk.impl
Core utilities for parsing our 'fnk'-style binding syntax.
Documented and tested through the actual 'letk','fnk', and 'defnk'
macros in plumbing.core.
The core entry points into this namespace are 'letk*' and 'fnk*',
which parse the new binding syntax and generate fnk bodies,
respectively.
For efficiency, two different methods of generating fnk bodies are
used. If the fnk takes a fixed set of arguments (i.e., no & or
:as), then a 'positional' version of the fnk that is called like an
ordinary Clojure fn (e.g., (f a b) rather than (f {:a a :b b}) is
generated as an implementation detail, and stored in metadata of
the actual keyword fnk (which is just a thin wrapper around the
positional version). If '& or :as are used, no such positional
function is generated.
The advantage of these 'positional' functions is that they can be
accessed using 'efficient-call-forms' or 'positional-fn' to call
the fnk without incurring the overhead of producing and then
destructuring a top-level map. See plumbing.graph.positional for
an example use.
+none+
A sentinel value used to indicate a non-provided optional value in a positional form.
letk-arg-bind-sym-and-body-form
(letk-arg-bind-sym-and-body-form env map-sym binding key-path body-form)
Given a single element of a single letk binding form and a current body form, return
a map {:schema-entry :body-form} where schema-entry is a tuple
[bound-key schema external-schema?], and body-form wraps body with destructuring
for this binding as necessary.
letk-input-schema-and-body-form
(letk-input-schema-and-body-form env binding-form key-path body-form)
Given a single letk binding form, value form, key path, and body
form, return a map {:input-schema :external-input-schema :map-sym :body-form}
where input-schema is the schema imposed by binding-form, external-input-schema
is like input-schema but includes user overrides for binding vectors,
map-sym is the symbol which it expects the bound value to be bound to,
and body-form wraps body in the bindings from binding-form from map-sym.
name-sym
(name-sym x)
Returns symbol of x's name.
Converts a keyword/string to symbol, or removes namespace (if any) of symbol
positional-arg-bind-sym-and-body
(positional-arg-bind-sym-and-body env binding body-form)
Given a single element of a fnk binding form and a current body form, return
a pair [[k bind-sym] new-body-form] where bind-sym is a suitable symbol to bind
to k in the fnk arglist (including tag metadata if applicable) and new-body-form
is wrapped with destructuring for this binding as necessary.
positional-arg-bind-syms-and-body
(positional-arg-bind-syms-and-body env bind body-form)
Given a fnk binding form and body form, return a pair
[bind-sym-map new-body-form] where bind-sym-map is a map from keyword args
to binding symbols and and new-body-form wraps body to do any extra processing
of nested or optional bindings above and beyond the bindings achieved by
bind-sym-vector.
positional-fn
(positional-fn fnk arg-ks)
Given argument order in arg-ks, produce an ordinary fn that can be called
with arguments in this order. arg-ks must include all required keys of fnk.
Example: (= ((positional-fn a-fnk [:b :a]) [1 2]) (a-fnk {:a 2 :b 1}))
Can only be applied to fnks with a positional form, and should yield
a function that is significantly faster than calling fnk directly by
avoiding the construction and destructuring of the outer map. Uses 'eval',
so while the produced function is fast, the actual production of the
positional-fn is generally relatively slow.
positional-info
(positional-info fnk)
If fnk has a positional function implementation, return the pair
[positional-fn positional-arg-ks] such that if positional-arg-ks is [:a :b :c],
calling (positional-fn a b c) is equivalent to calling (fnk {:a a :b b :c c}),
but faster. Optional values to fnk can be simulated by passing +none+ as the
value, i.e., (positional-fn +none+ b +none) is like (fnk {:b b}).
qualified-sym
(qualified-sym x)
Returns qualified symbol of x, an instance of Named
schema-override
(schema-override sym schema)