Liking cljdoc? Tell your friends :D

commensura.provenance

Opt-in build history — "how did I get here?" — for commensura values.

When recording is on, each public verb tags its result with a self-contained provenance node in the value's Clojure metadata: the operation, the result value, and the operand sub-nodes nested inline. So (meta result) holds the entire history as one ::node map — you can read the whole tree by eye, no walker required.

(require '[commensura.core :refer [with-provenance by to]] '[commensura.provenance :refer [explain]] '[commensura.units :as u])

(with-provenance (explain (to (by (u/feet 10) (u/feet 12) (u/feet 8)) u/gallons)))

The two entry points for making history — with-provenance (turn recording on) and defstep (define a fn that records as one node) — live in commensura.core, alongside the verbs they drive. This namespace holds the mechanism (step/record-node, the *record-provenance-on-step* var) and everything for reading history back.

Off by default, zero-cost when off. Recording is gated by the dynamic var *record-provenance-on-step* (default false); commensura.core/with-provenance binds it true for its body. When it's off the verbs do no vary-meta at all — they don't even build the operand vector.

Each step forgets its internals. A step evaluates its body with recording suppressed, then records exactly one node for itself. So a verb records a single node over its operands, and a defstep'd function (like commensura.math/sqrt) shows only its own name — never the pow it calls underneath. The operands' own histories, built before the step ran, are nested in unchanged.

It's a DAG, not a tree. The nested sub-nodes are shared immutable maps, so a let-bound value reused in two operands is the same node object in both places (identical? holds); explain shows the repeat once, citing it thereafter as a back-reference (↑ [n]).

Only real values carry history, and it's process-local. Metadata rides on IObj values; raw scalars, exponents and keyword targets appear as inline operand leaves, never as nodes. Because pr/read ignore metadata, a recorded value is still = to, and prints identically to, its unrecorded self — history lives only in memory.

Inspect with node (the nested map), history (its nodes as a flat seq), history-zip (a clojure.zip cursor over the whole tree — nodes and leaves), and explain/explain-str/ explain-lines (a readable outline — printed, as one string, or as a seq of line-strings — itself written on history-zip).

Opt-in **build history** — "how did I get here?" — for commensura values.

When recording is on, each public verb tags its result with a self-contained provenance *node* in
the value's Clojure metadata: the operation, the result value, and the operand *sub-nodes* nested
inline. So `(meta result)` holds the entire history as one `::node` map — you can read the whole tree
by eye, no walker required.

  (require '[commensura.core :refer [with-provenance by to]]
           '[commensura.provenance :refer [explain]]
           '[commensura.units :as u])

  (with-provenance
    (explain (to (by (u/feet 10) (u/feet 12) (u/feet 8)) u/gallons)))

The two entry points for *making* history — `with-provenance` (turn recording on) and `defstep`
(define a fn that records as one node) — live in `commensura.core`, alongside the verbs they drive.
This namespace holds the mechanism (`step`/`record-node`, the `*record-provenance-on-step*` var) and
everything for *reading* history back.

**Off by default, zero-cost when off.** Recording is gated by the dynamic var
`*record-provenance-on-step*` (default `false`); `commensura.core/with-provenance` binds it true for
its body. When it's off the verbs do no `vary-meta` at all — they don't even build the operand vector.

**Each step forgets its internals.** A `step` evaluates its body with recording *suppressed*, then
records exactly one node for itself. So a verb records a single node over its operands, and a
`defstep`'d function (like `commensura.math/sqrt`) shows only its own name — never the `pow` it calls
underneath. The operands' *own* histories, built before the step ran, are nested in unchanged.

**It's a DAG, not a tree.** The nested sub-nodes are shared immutable maps, so a `let`-bound value
reused in two operands is the *same* node object in both places (`identical?` holds); `explain` shows
the repeat once, citing it thereafter as a back-reference (`↑ [n]`).

**Only real values carry history**, and it's **process-local.** Metadata rides on `IObj` values;
raw scalars, exponents and keyword targets appear as inline operand leaves, never as nodes. Because
`pr`/read ignore metadata, a recorded value is still `=` to, and prints identically to, its
unrecorded self — history lives only in memory.

Inspect with `node` (the nested map), `history` (its nodes as a flat seq), `history-zip` (a
`clojure.zip` cursor over the whole tree — nodes and leaves), and `explain`/`explain-str`/
`explain-lines` (a readable outline — printed, as one string, or as a seq of line-strings — itself
written on `history-zip`).
raw docstring

*record-provenance-on-step*clj

When true, the public verbs record a provenance node on each result. Default false — bind it with commensura.core/with-provenance (or directly) to record. Kept off by default so ordinary use pays nothing.

When true, the public verbs record a provenance node on each result. Default false — bind it with
`commensura.core/with-provenance` (or directly) to record. Kept off by default so ordinary use pays
nothing.
sourceraw docstring

child-nodesclj

(child-nodes x)

The inputs of x that are themselves nodes — the DAG children (inline leaves dropped).

The inputs of `x` that are themselves nodes — the DAG children (inline leaves dropped).
sourceraw docstring

explainclj

(explain x)
source

explain-linesclj

(explain-lines x)

x's build history as a seq of outline line-strings — the data explain-str joins and explain prints. A node line reads [n] <value> ← <verb>; inline operands sit unnumbered beneath their verb; a value that recurs is shown once, then cited as ↑ [n] (and its operands omitted). Returned as data so you can count/filter/re-indent it or feed it to a viewer.

Walks history-zip, dogfooding the cursor: zip/path gives the indentation depth; seen (a plain map threaded through the loop) numbers nodes and de-duplicates them by value; and once a repeat is cited, hide (the depth it sat at) omits every deeper loc until the walk climbs back out — so no manual subtree-skipping is needed.

`x`'s build history as a seq of outline line-strings — the data `explain-str` joins and `explain`
prints. A node line reads `[n] <value>  ←  <verb>`; inline operands sit unnumbered beneath their
verb; a value that recurs is shown once, then cited as `↑ [n]` (and its operands omitted). Returned
as data so you can count/filter/re-indent it or feed it to a viewer.

Walks `history-zip`, dogfooding the cursor: `zip/path` gives the indentation depth; `seen` (a plain
map threaded through the loop) numbers nodes and de-duplicates them *by value*; and once a repeat is
cited, `hide` (the depth it sat at) omits every deeper loc until the walk climbs back out — so no
manual subtree-skipping is needed.
sourceraw docstring

explain-strclj

(explain-str x)
source

historyclj

(history x)

Every node reachable from x, x's node first, depth-first. A shared node repeats (it's the same object each time — distinct collapses them; explain shows it once with a back-reference).

Every node reachable from `x`, `x`'s node first, depth-first. A shared node repeats (it's the same
object each time — `distinct` collapses them; `explain` shows it once with a back-reference).
sourceraw docstring

history-zipclj

(history-zip x)

A clojure.zip cursor over x's history — pass a recorded value or a node map. Unlike history (nodes only), this walks the whole tree: a branch's children are all its :inputs, so zip/down reaches the inline-operand leaves too. Read the node/leaf under the cursor with clojure.zip/node, move with clojure.zip/next/down/up/right/left. explain is written on top of it.

A `clojure.zip` cursor over `x`'s history — pass a recorded value *or* a node map. Unlike `history`
(nodes only), this walks the **whole** tree: a branch's children are all its `:inputs`, so `zip/down`
reaches the inline-operand leaves too. Read the node/leaf under the cursor with `clojure.zip/node`,
move with `clojure.zip/next`/`down`/`up`/`right`/`left`. `explain` is written on top of it.
sourceraw docstring

inputsclj

(inputs x)

The operand sub-nodes/leaves of x, in order (nil: a leaf).

The operand sub-nodes/leaves of `x`, in order (nil: a leaf).
sourceraw docstring

nodeclj

(node x)

The provenance node — a nested {:op :value :inputs} map — for x, or nil if it carries none. Accepts a value (reads its metadata) or a node map (returns it), so the inspection fns take either.

The provenance node — a nested `{:op :value :inputs}` map — for `x`, or nil if it carries none.
Accepts a value (reads its metadata) or a node map (returns it), so the inspection fns take either.
sourceraw docstring

opclj

(op x)

The verb that produced x (nil for a leaf).

The verb that produced `x` (nil for a leaf).
sourceraw docstring

record-nodeclj

(record-node op inputs result)

Attach a provenance node to result (an IObj value): its op, the result value, and each input folded in as a nested sub-node or a leaf. A non-IObj result (a bare number, a boolean) is returned unchanged. Callers gate on *record-provenance-on-step* first (see step).

Attach a provenance node to `result` (an IObj value): its op, the result value, and each input
folded in as a nested sub-node or a leaf. A non-IObj result (a bare number, a boolean) is returned
unchanged. Callers gate on `*record-provenance-on-step*` first (see `step`).
sourceraw docstring

recorded?clj

(recorded? x)

Does x carry a provenance node?

Does `x` carry a provenance node?
sourceraw docstring

stepcljmacro

(step op inputs & body)

Record body's result as one provenance node labelled op over inputs (its operand values). A no-op — and zero allocation — unless *record-provenance-on-step* is on. The body runs with recording suppressed, so a step keeps no trace of the ops it calls internally: (step #'sqrt [x] …) records a lone sqrt node, and the operands' own histories (built before the step) nest in. op is conventionally the fn's #'var (a fully-qualified reference), so a node names exactly what made it.

Record `body`'s result as one provenance node labelled `op` over `inputs` (its operand values).
A no-op — and zero allocation — unless `*record-provenance-on-step*` is on. The body runs with
recording *suppressed*, so a step keeps no trace of the ops it calls internally: `(step #'sqrt [x] …)`
records a lone `sqrt` node, and the operands' own histories (built before the step) nest in. `op` is
conventionally the fn's `#'var` (a fully-qualified reference), so a node names exactly what made it.
sourceraw docstring

valueclj

(value x)

The result value stored on x's node (nil for a leaf).

The result value stored on `x`'s node (nil for a leaf).
sourceraw docstring

cljdoc builds & hosts documentation for Clojure/Script libraries

Keyboard shortcuts
Ctrl+kJump to recent docs
Move to previous article
Move to next article
Ctrl+/Jump to the search field
× close