Pure composition of runtime branches onto a tool's contributed commands.
A BRANCH extends or wraps one path of a tool's command tree, at any depth:
graft git belt hello beside what git belt already routes
around middleware, (fn [next] handler), over a verb, a subtree or the tool
The host re-reads contributions on every call and lets a contribution win over its own verb of the same name, so composing HERE, on the way out of the store, needs nothing from the host. Touching a root the host itself owns contributes that root, with a re-entry into the tool as its default route: the host's own verb is still what answers everything no branch took.
A leaf that routes its own remainder is SPLIT, never replaced: it becomes {:_handler leaf, seg branch} and still receives the whole :command.
A graft never shadows a route; changing one is what around is for.
No reader conditionals, as for the registry above it. Catching a platform exception is therefore the :guard the host injects.
Pure composition of runtime branches onto a tool's contributed commands.
A BRANCH extends or wraps one path of a tool's command tree, at any depth:
graft `git belt hello` beside what `git belt` already routes
around middleware, (fn [next] handler), over a verb, a subtree or the tool
The host re-reads contributions on every call and lets a contribution win over
its own verb of the same name, so composing HERE, on the way out of the store,
needs nothing from the host. Touching a root the host itself owns contributes
that root, with a re-entry into the tool as its default route: the host's own
verb is still what answers everything no branch took.
A leaf that routes its own remainder is SPLIT, never replaced: it becomes
{:_handler leaf, seg branch} and still receives the whole :command.
A graft never shadows a route; changing one is what `around` is for.
No reader conditionals, as for the registry above it. Catching a platform
exception is therefore the :guard the host injects.(compose specs branches tool {:keys [routes next-handler guard]})SPECS, a tool's contributions {command spec}, with BRANCHES composed in. Returns {:specs :refusals}.
HOST {:routes #{command} :next-handler h :guard g}. A branch on a root nobody contributed needs HOST to tell whether the host's own tree routes that root: it is then seeded with :next-handler, the re-entry that reaches the host's verb. With no :routes such a branch is refused, because a contribution of that name would otherwise replace a verb this cannot see.
SPECS, a tool's contributions {command spec}, with BRANCHES composed in.
Returns {:specs :refusals}.
HOST {:routes #{command} :next-handler h :guard g}. A branch on a root nobody
contributed needs HOST to tell whether the host's own tree routes that root: it
is then seeded with :next-handler, the re-entry that reaches the host's verb.
With no :routes such a branch is refused, because a contribution of that name
would otherwise replace a verb this cannot see.(current x)The value X denotes right now, following vars to a fixed point (bounded).
The value X denotes right now, following vars to a fixed point (bounded).
(failure {:keys [kind path owner]} tool message)The answer of a branch that threw, for a host's :guard: who and where.
The answer of a branch that threw, for a host's :guard: who and where.
(flatten-graft path node)Every [path leaf] a graft of NODE at PATH makes routable. A verb map becomes one entry per leaf, so grafts merge key by key. A leaf stays as registered, so a var stays a var.
Every [path leaf] a graft of NODE at PATH makes routable. A verb map becomes one entry per leaf, so grafts merge key by key. A leaf stays as registered, so a var stays a var.
(fold tree branches tool opts)TREE with BRANCHES applied. Returns {:tree :refusals}.
Grafts first, shallowest first, so a graft at [:a] and at [:a :b] compose in either arrival order. Arounds after, so one can wrap a graft. Lowest :order runs outermost; ties break by owner, so arrival order never decides.
OPTS: :declared (fn [root]) -> verbs an opaque root routes; :routes #{command} the host routes; :guard (fn [branch tool f]) -> f as dispatched.
TREE with BRANCHES applied. Returns {:tree :refusals}.
Grafts first, shallowest first, so a graft at [:a] and at [:a :b] compose in
either arrival order. Arounds after, so one can wrap a graft. Lowest :order runs
outermost; ties break by owner, so arrival order never decides.
OPTS: :declared (fn [root]) -> verbs an opaque root routes; :routes #{command}
the host routes; :guard (fn [branch tool f]) -> f as dispatched.(handler? x)Is X invocable code, or a var holding it? Data is ifn? too and is not a handler.
Is X invocable code, or a var holding it? Data is `ifn?` too and is not a handler.
(parse-path path)PATH as a vector of keywords: "belt hello", ["belt" :hello] or :belt. Blank or nil is [], which names the whole tool.
PATH as a vector of keywords: "belt hello", ["belt" :hello] or :belt. Blank or nil is [], which names the whole tool.
(path-str path)PATH as the command string a caller sends.
PATH as the command string a caller sends.
(tokens s)S split on runs of whitespace, blanks dropped.
S split on runs of whitespace, blanks dropped.
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 |