schema.expr
The serializable expression AST behind the lambda-bound operations in com.eignex.kumulant.schema. When an operation needs a projection or a predicate that must travel on the wire rather than as a live Kotlin lambda, it carries one of these trees instead. The whole tree is serializable, so a filter or a transform round-trips as data and rebuilds an identical closure on the far side.
The three trees
There are three sealed hierarchies, one per result shape. ScalarExpr evaluates to a single number from an update's value, its paired second component, and the current vector. VectorExpr evaluates to a whole vector and backs the per-feature projection and scaling operations. BoolExpr evaluates to a boolean and drives filter predicates and the guards on conditional nodes. Each hierarchy is sealed, so serialization is closed and exhaustive: every node carries a discriminator and decoding can never land on an unknown shape.
Leaves and operators
The scalar leaves are the update value X, the paired second component Y, a vector coordinate V, and a literal Const. Arithmetic composes them with the ordinary operators and with dedicated nodes for the transcendental functions: powers, logs, exponentials, square roots, and absolute value. Comparisons between scalars produce a BoolExpr, and the boolean combinators join several predicates into one.
Sugar nodes
Common shapes have dedicated nodes so a serialized tree stays readable rather than ballooning into nested arithmetic. Standardizing, min-max scaling, centering, and range tests each have their own node, as does the multi-branch Switch and the conditional IfExpr. Vector projection has nodes for dot products, element selection, single-coordinate access, and a fold whose operator picks sum, min, max, or mean.
Anything that cannot be expressed as one of these nodes stays a live-only lambda on the com.eignex.kumulant.core.Stat side and is not wire-expressible. Reach for the lambda overloads of the filter and transform operations in com.eignex.kumulant.operation when that happens.
Types
Wire-serialisable AST for boolean predicates over the same input environment as ScalarExpr. Consumed by every spec-side filter operator and by IfExpr's condition slot.
Reads the center field of the feedback primary's snapshot. Requires the primary's result to implement HasCenterScale; raises IllegalStateException when evaluated without a primary, or when the primary's result does not expose a center.
Wire spec for a constant scalar.
Reads the max field of the feedback primary's snapshot. Requires the primary's result to implement HasMinMax; raises IllegalStateException when evaluated without such a primary.
Wire spec for a ternary if (cond) then else otherwise.
Reads the min field of the feedback primary's snapshot. Requires the primary's result to implement HasMinMax; raises IllegalStateException when evaluated without such a primary.
Min-max projection mapping X from [primary.min, primary.max] to [targetLow, targetHigh], emitting targetLow while the running range is still degenerate. Reusable AST sugar for the min-max-scaler pattern; requires a HasMinMax primary.
Wire-serialisable AST for scalar expressions over the per-update input environment. The library uses these wherever a stat needs to apply a caller-supplied projection / weight / threshold expression that has to round-trip on the wire; weightBy, transform, the per-bin scaler projections, the WithFeedback op, the loss / pinball / quantile configurations.
Reads the scale field of the feedback primary's snapshot. Requires the primary's result to implement HasCenterScale; raises IllegalStateException when evaluated without a primary, or when the primary's result does not expose a scale.
Z-score projection: (X - Center) / Scale, emitting 0 when Scale is still zero. Reusable AST sugar for the standard-scaler pattern; requires a HasCenterScale primary.
Multi-way branch on a scalar key. Replaces nested IfExpr cascades. The first case whose SwitchCase.value equals on.eval(...) exactly wins; if none match, otherwise is returned.
v[index] - out-of-bounds throws at eval time.
Wire-serialisable AST for vector-valued expressions over the same input environment as ScalarExpr / BoolExpr. Used by the spec-side transformVector(VectorExpr) operator when the output is a fresh vector rather than a per-element transform.
In element-wise feedback contexts (vector / regression / paired), returns the coordinate index of the currently evaluating element as a Double. Outside such contexts (primary is not an IndexedResult), raises IllegalStateException.
Refers to the primary scalar input x.
Refers to the secondary scalar input y (paired stats only).
Functions
Build Div of two expressions.
Divide this expression by a literal rhs.
Divide a literal receiver by an expression.
Exact equality (no tolerance).
Exact equality against a literal (no tolerance).
Greater-or-equal comparison.
Greater-or-equal against a literal.
Strictly-greater-than comparison.
Strictly-greater-than against a literal.
Less-or-equal comparison.
Less-or-equal against a literal.
Strictly-less-than comparison.
Strictly-less-than against a literal.
Build Sub of two expressions.
Subtract a literal rhs from this expression.
Subtract an expression from a literal receiver.
Build Add of two expressions.
Add a literal rhs to this expression.
Add an expression to a literal receiver.
Build Mul of two expressions.
Multiply this expression by a literal rhs.
Multiply a literal receiver by an expression.
Unary minus: wraps in Neg.