Query
Value-producing atom. Computes from operands or reads from Context. Never transforms Context.
Properties
- Mutation: none - declares no mutation slot. Its own tracked effects are ⊆ {READ}. (May be pure: no effects at all.)
- Children: Queries only.
- Yields: one value (Scalar) or N values (Stream); see sub-shapes below.
Sub-shapes
| Sub-shape | Yields | Source | Examples |
|---|---|---|---|
| ScalarQuery | one value | held / operands / ref / stream | Literal(5), Add, Eq, ref.fetch(), Collect, First |
| StreamQuery | N values | source stream or ref collection | Map, Filter, Take, ItemsOf, KeysOf, ForEach |
Literal is a notable Scalar: irreducible leaf, holds a value, yields it once. The trivial Query, pure (no effects). Worth flagging because most non-Ref leaves are Literals.
Composition
- Q in Q. Functional composition: child yields a value, parent consumes it.
- Iterator stacking.
Filter(Map(ItemsOf(ref), x+1), x>0)- stream lenses stacked, no intermediate materialization. - Scalars over streams. A Scalar can consume a Stream child by pulling and folding (e.g.
Collect(Filter(ItemsOf(ref), p)),First(stream)). This is what bridges the otherwise-REFUSED scalar-asks-stream cell of the realization matrix.
Forms
Literal(5)
Add(Literal(2), ref.fetch())
Map(ItemsOf(ref), x + 1)
Filter(Map(ItemsOf(ref), x + 1), x > 0)
Collect(Filter(ItemsOf(ref), p))
First(StreamQuery(...))Examples
| Expression | Sub-shape | Effects |
|---|---|---|
Literal(42) | Scalar | pure |
Add(Literal(2), Literal(3)) | Scalar | pure |
ref.fetch() | Scalar | READ |
Eq(ref.fetch(), Literal(0)) | Scalar | READ |
If(cond_q, a_q, b_q) | Scalar | derived |
ItemsOf(coll_ref) | Stream | READ |
Map(ItemsOf(ref), x+1) | Stream | READ |
ForEach(items, x+1) | Stream | derived |
Collect(Filter(...)) | Scalar | derived |
First(stream_q) | Scalar | derived |
Constraints
- No Command children. Commands yield nothing - breaks the value chain.
- No Flow children. Same reason - Flow yields nothing.
- Action children allowed. Actions yield (Q's contract) and mutate Context (Q's old no-WRITE promise relaxes when Action is in play). A ScalarAction drops straight into a scalar slot; a StreamAction yields a stream, so a scalar Query reduces it like any StreamQuery. Q's yield-side contract is unchanged; its
composition_effectsmay now include WRITE through Action descendants.
Why this kind
Computation composes naturally as functional expressions. Q is the algebraic backbone of the model: associativity, parallelism on independence, common-subexpression. Pure compute or Context-using read; never mutation.
Bare verb vs *Do
ForEach, If, Map are Queries (yield values, compose like expressions). The *Do variants (ForEachDo, IfDo) are Flows that compose Commands. Same author intent, different algebras. See kinds for the convention.