Span
Transparent Interaction. The Interaction sub-kind that wraps a body to define a region (lifecycle, policy) governing how it runs. Does no work of its own; it forwards the body's yield in the same shape and protocol. The Span atom is always a Span - parents slot-fit a Span by looking through to the body's yield, not by re-typing.
Properties
- Own effects: any. no restriction.
- Children: body: any Nu (Ref, Query, Command, Flow, or another Span), auxiliary children: any.
- Yields: exactly what the body yields, in the same shape (one value, a stream, or nothing).
Sub-shapes
| Sub-shape | Governs | Hooks / mechanism | Examples |
|---|---|---|---|
| Bracket | lifecycle | before / after / after_failure | Snapshot, Transaction |
| Policy | execution | re-run / fall back on failure | Retry, TryCatch |
Forms
# Bracket
Snapshot(body)
Transaction(body)
# Policy
Retry(body, attempts_q)
TryCatch(body, fallback_body)Examples
| Expression | Body kind | Span sub-shape | Body yields |
|---|---|---|---|
Snapshot(view_ref) | Ref | Bracket | one value |
Snapshot(ForEach(items_q, x+1)) | Query | Bracket | a stream |
Snapshot(ForEachDo(items, Print)) | Flow | Bracket | nothing |
Transaction(ForEachDo(items, Store(ref[i], v))) | Flow | Bracket | nothing |
Retry(Store(ref, q), 3) | Command | Policy | nothing |
TryCatch(Transaction(body), fallback) | Span | Policy | body-dependent |
Composition
- One body child. Required. The Span is meaningless without it.
- Body can be any Nu: Ref, Query, Command, Flow, or another Span. Span is cross-cutting.
- Spans nest.
Transaction(Snapshot(body))is fine - each adds its own region around the inner body. - Auxiliary children (e.g.
attempts_qin Retry,fallback_bodyin TryCatch) sit alongside the main body; the Span consumes them internally.
Constraints
- Body is required. Empty Span is structurally invalid - nothing to wrap.
- Yield-shape mirrors body. A Span over a stream body yields a stream; over a scalar body yields a scalar; over a body that yields nothing, yields nothing. The Span atom remains a Span; only the yield is forwarded.
Atomic re-evaluation
A Span that re-runs or rolls back its body (Retry, Transaction) treats each attempt as a fresh, complete evaluation of the body, whatever its cardinality - the body is one child, and re-running it does not depend on its shape. For a stream body this means the attempt realizes the stream inside the region (drains it, emits only on success); a retry never resumes a half-drained stream or replays an already-emitted prefix. Bounded streams only - an unbounded body never completes an attempt.
Why this sub-kind
Some concerns - lifecycle (snapshot, transaction), execution policy (retry, fallback) - apply uniformly to Queries, Commands, and Flows alike. Folding them into one of the work sub-kinds would either pollute that sub-kind with control concerns or duplicate the construct three times (one per work sub-kind).
Span isolates these concerns as a fourth, transparent sub-kind of Interaction. The body does what it does; the Span shapes the surroundings. Composition continues to see the body's yield - the Span atom forwards it unchanged.