Thin layer over dynamic vars for implicit dependency injection. Dynjs can be used to have better control over side effects, to abstract over different possible interpretations of an aspect of a program or to make things easier for testing.
First we declare a dynj named eff
, which expects a single argument.
(declare-dynj eff [a])
Note that eff
itself can already be called, but it's "abstract" in the
sense that without a bound implementation/interpreter, it cannot do anything.
Hence the following will throw an exception:
(eff 2)
Let's say foo
is a usage site of eff
. (Of course, calling foo
now will
still throw the same exception as above.)
(defn foo [s]
(assert (= 4 (eff 2))))
With binding
we can interpret eff
as, say, a square
function locally.
(defn square [a] (* a a))
(binding [eff square]
(foo 5)) ;; => this works now
Thin layer over dynamic vars for implicit dependency injection. *Dynjs* can be used to have better control over side effects, to abstract over different possible interpretations of an aspect of a program or to make things easier for testing. ### Example First we declare a *dynj* named `eff`, which expects a single argument. ``` (declare-dynj eff [a]) ``` Note that `eff` itself can already be called, but it's "abstract" in the sense that without a bound implementation/interpreter, it cannot do anything. Hence the following will throw an exception: ``` (eff 2) ``` Let's say `foo` is a usage site of `eff`. (Of course, calling `foo` now will still throw the same exception as above.) ``` (defn foo [s] (assert (= 4 (eff 2)))) ``` With `binding` we can interpret `eff` as, say, a `square` function locally. ``` (defn square [a] (* a a)) (binding [eff square] (foo 5)) ;; => this works now ```
(bind-fn* binding-map f)
Returns a function that will call f
with the given map of dynj
implementations in place. Note that the returned function can then
be called on other threads, too.
Returns a function that will call `f` with the given map of dynj implementations in place. Note that the returned function can then be called on other threads, too.
(binding bindings & body)
Binds one or more dynjs to implementations during the evaluation of body
.
(declare-dynj add-user! [user])
(binding [add-user! db-add-user!]
...)
Binds one or more dynjs to implementations during the evaluation of `body`. ``` (declare-dynj add-user! [user]) (binding [add-user! db-add-user!] ...) ```
(bound-fn* f)
Returns a function that will call f
with the same dynj
implementations in place as there are now. Passes all arguments though to f.
Returns a function that will call `f` with the same dynj implementations in place as there are now. Passes all arguments though to f.
(declare-dynj name params)
(declare-dynj name docstring params)
Declares name
as a dynamic injection point, to be bound to an
implementation/value later via binding
. params
and docstring
are for documentation purposes.
Declares `name` as a dynamic injection point, to be bound to an implementation/value later via [[binding]]. `params` and `docstring` are for documentation purposes.
(defn-dynj name params & body)
Declares name
as a dynamic injection point, to be bound to an
implementation/value later via binding
, and adds a default implementation.
Typically you would throw a helpful exception in body
.
Declares `name` as a dynamic injection point, to be bound to an implementation/value later via [[binding]], and adds a default implementation. Typically you would throw a helpful exception in `body`.
(merge-dynjs binding-map & more)
Like merge, but asserts that all keys are dynj vars, and the same vars are not bound to different implementations.
Like merge, but asserts that all keys are dynj vars, and the same vars are not bound to different implementations.
(with-bindings* binding-map thunk)
Calls (thunk)
and binds implementations via a map of
dynj vars during the evaluation of (thunk)
.
Calls `(thunk)` and binds implementations via a map of dynj vars during the evaluation of `(thunk)`.
cljdoc is a website building & hosting documentation for Clojure/Script libraries
× close