Expand description
The view, as a dataflow plan rather than as one expression.
docs/05-tier-lowering.md §5.3:
a thousand connected users of
todos.map(filter_by(session.user))must compile to one shared dataflow whose final per-session operators (filter, project, diff) run per subscriber
and docs/03-type-and-effect-system.md §3.8:
remainingupdates by ±1 per event, never by recount.
crate::split produces a Core function of the accumulator — full recompute per event,
which Phase 1 called “semantically final, later made incremental”. crate::incremental
answers which vertices a plan could maintain. This module is the plan itself: the same view,
decomposed into operators that a delta can flow through, with crate::engine as the thing
that flows them.
§What an operator is
Two kinds, and the distinction is the whole design:
- A delta operator (
Op::MapValues,Op::MapList,Op::FilterList,Op::SortBy,Op::Concat,Op::Flatten,Op::FlatMap,Op::Count,Op::IsEmpty) holds an ordered arrangement — its output as a keyed collection — and updates it from the changes at its input. Work is proportional to the change, not to the collection. - A pointwise operator (
Op::Pointwise) holds a value and recomputes it when an input changed. That is what today’s runtime does for the whole view, so a plan of nothing but pointwise operators is exactly as fast as no plan at all — and no slower, which is what makes this safe to switch on for every program.
Everything the decomposition cannot see through becomes one pointwise operator over the plan
nodes it reads: a match, an if, a call through a value, a primitive with no delta rule. The
fallback is the reason the engine can be correct for programs it cannot accelerate, and
Node::because records which construct forced it so beck explain incremental can say so.
§Where the keys come from
An arrangement is a BTreeMap from an ordering key to a value, and the key is what makes the
output’s order a consequence of the plan rather than of a sort at the end. Iteration order
reaches the rendered page and the replay digest (crate::pmap), so an incremental view that
produced the right entries in a different order would be a correctness bug, not a cosmetic one.
| operator | key |
|---|---|
map_values(m) | the map’s key — so the arrangement is already in the order map_values yields |
map_list, filter_list | the input’s key, unchanged: neither moves an element |
sort_by(xs, k) | k(x) followed by the input’s key — a stable sort, expressed as an order |
concat_lists([a, b]) | the input’s position, followed by that input’s key |
flatten, flat_map | the input’s key, followed by the position inside that element’s list |
§What this is not
It is not a query plan. §4.2 keeps the Query sub-language symbolic and nothing compiles one;
this compiles the signal graph, which is a different thing that happens to share the word.
beck explain query prints this, and crate::fuse rewrites it.
Structs§
- Fun
- A function an operator applies per element, closed over the plan nodes it reads.
- Node
- Plan
- The view as a dataflow.
Enums§
- Op
- What one operator does.
Constants§
- OPERATORS
- Every operator the engine implements, by name.
Functions§
- cost_
report beck explain cost— what one event costs this view.- query_
report beck explain query— the view as a dataflow plan, operator by operator.