Functions and reducers
Two kinds of function are callable without registering anything. A registered host function of the same name shadows either.
Aggregate reducers
Declared under aggregates on the report or on a group.
| Reducer | Result | Empty |
|---|---|---|
sum:=expr |
total of expr |
0 |
count |
number of rows | 0 |
countDistinct:=expr |
distinct values of expr |
0 |
avg:=expr |
mean of expr |
null |
min:=expr |
smallest expr |
null |
max:=expr |
largest expr |
null |
count takes no expression. Every other reducer takes the form
name:=expression. Give avg, min and max a visible marker where an empty
set matters.
Run reducers
Declared under run, and read as run.<name> on a detail row. The six above,
plus one.
| Reducer | run.<name> on each row |
|---|---|
sum:=expr |
cumulative sum up to and including this row |
count |
1-based running count |
countDistinct:=expr |
distinct values seen so far |
avg:=expr |
cumulative mean so far |
min:=expr, max:=expr |
running extreme so far |
prev:=expr |
expr of the previous row, null on the first |
Scope decides the reset. A run block on the report persists across the
document. A run block on a group starts again at each instance. Run names
can’t repeat across the report and nested groups, because every run value
shares one run object.
Scalar built-ins
One value in, one value out. These are function calls only, never a reducer
declaration, so "total": "round:[email protected]" is a definition error.
| Function | Result |
|---|---|
round(x, n?) |
x to n decimal places, halves away from zero |
floor(x, n?) |
x to n decimal places, towards negative infinity |
ceil(x, n?) |
x to n decimal places, towards positive infinity |
abs(x) |
the magnitude of x |
They round the decimal you wrote, not the double it’s stored as, so
round(2.675, 2) is 2.68.
n defaults to 0 and must be a number from 0 to 100. A fractional n
truncates to whole places. Anything outside that’s an error naming the cell
and the call. A non-finite x passes through untouched rather than folding to
zero.
min and max are reducer names and aren’t scalar two-argument functions.
min(1, 2) is a render error saying so. trunc isn’t built in.
Inline reducers
A reducer also folds an array on the row itself.
{ "value": "{{ sum(@.lines, l => l.total) }}" }Registered functions
type FunctionRegistry = Record<string, (...args: any[]) => any>Passed as the second argument to report or plan. Registered functions count
as trusted configuration, the same standing as the definition. A compiled report
lists the ones it calls on report.functions, each as a { name, arity, doc? }
signature in call-first-seen order.