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.
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.
A sentinel value used to indicate a non-provided optional value in a positional form.
A sentinel value used to indicate a non-provided optional value in a positional form.
(efficient-call-forms fnk arg-form-map)
Get [f arg-forms] that can be used to call a fnk most efficiently, using the positional version if available, or otherwise the raw fnk. arg-form-map is a map from keywords representing arguments to fnk to forms that evaluate to the corresponding arguments.
The basic idea is that (eval (cons f arg-forms)) would yield code for an efficient call to fnk. However, this form is not returned directly, because in most cases the literal function f cannot be directly evaluated due to a quirk in Clojure -- e.g., try (eval `(~(let [x 1] (fn [y] (+ y x))) 2)).
For examples of how this is used, see 'positional-fn' below, or the positional compilation in plumbing.graph.positional.
Get [f arg-forms] that can be used to call a fnk most efficiently, using the positional version if available, or otherwise the raw fnk. arg-form-map is a map from keywords representing arguments to fnk to *forms* that evaluate to the corresponding arguments. The basic idea is that (eval (cons f arg-forms)) would yield code for an efficient call to fnk. However, this form is not returned directly, because in most cases the literal function f cannot be directly evaluated due to a quirk in Clojure -- e.g., try (eval `(~(let [x 1] (fn [y] (+ y x))) 2)). For examples of how this is used, see 'positional-fn' below, or the positional compilation in plumbing.graph.positional.
(fnk-form env name? bind body form)
Take an optional name, binding form, and body for a fnk, and make an IFn/PFnk for these arguments.
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.
Take an optional name, binding form, and body for a fnk, and make an IFn/PFnk for these arguments. 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.
(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.
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 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.
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 x)
Returns symbol of x's name. Converts a keyword/string to symbol, or removes namespace (if any) of symbol
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 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.
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 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.
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 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.
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-fnk-form fn-name
external-input-schema
ordered-ks->opt
arg-sym-map
body
form)
Takes an optional name, input schema, seq of ordered [key optional?] pairs, an arg-sym-map from these keywords to symbols, and and a positional fn body that can reference these symbols. Produces a form generating a IFn/PFnk that can be called as a keyword function, and has metadata containing the positional function for efficient compilation as described in 'efficient-call-forms' and 'positional-fn' above, with argument order the same as in input-schema by default. Example:
(def f (eval (i/positional-fnk-form 'foo {:x s/Any (s/optional-key :y) s/Any} [`(+ ~'x (if (= ~'y i/+none+) 5 ~'y))])))
(= [6 3] [(f {:x 1}) (f {:x 1 :y 2})]) (= [6 3] [((i/positional-fn f [:x]) 1) ((i/positional-fn f [:y :x]) 2 1)]).
Takes an optional name, input schema, seq of ordered [key optional?] pairs, an arg-sym-map from these keywords to symbols, and and a positional fn body that can reference these symbols. Produces a form generating a IFn/PFnk that can be called as a keyword function, and has metadata containing the positional function for efficient compilation as described in 'efficient-call-forms' and 'positional-fn' above, with argument order the same as in input-schema by default. Example: (def f (eval (i/positional-fnk-form 'foo {:x s/Any (s/optional-key :y) s/Any} [`(+ ~'x (if (= ~'y i/+none+) 5 ~'y))]))) (= [6 3] [(f {:x 1}) (f {:x 1 :y 2})]) (= [6 3] [((i/positional-fn f [:x]) 1) ((i/positional-fn f [:y :x]) 2 1)]).
(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}).
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 x)
Returns qualified symbol of x, an instance of Named
Returns qualified symbol of x, an instance of Named
cljdoc is a website building & hosting documentation for Clojure/Script libraries
× close