---
title: "CX operators (generated)"
description: "Generated by scripts/generate-cx-ops-doc.ts (bun run generate:cx-ops) from OPS (packages/kernel/cx/src/ops). Do not edit by hand. The normative table is docs/design/kernel/cx.md §2.12; a row appears…"
order: 0
id: "cx/ops"
---

# CX operators (generated)

Generated by `scripts/generate-cx-ops-doc.ts (bun run generate:cx-ops)` from `OPS` (packages/kernel/cx/src/ops). Do not edit by hand.
The normative table is docs/design/kernel/cx.md §2.12; a row appears here once its family task adds its `OpDef`.

## logic {#logic}

| Row | Spelling | Signature | NULL rule | Faults | Summary | Example |
|---|---|---|---|---|---|---|
| L1 | `&&` (binary) | boolean × boolean → boolean | kleene | — | True when both conditions are true. | `isSet(due) && status == 'sent'` |
| L2 | `\|\|` (binary) | boolean × boolean → boolean | kleene | — | True when either condition is true. | `status == 'paid' \|\| isBlank(due)` |
| L3 | `!` (unary) | boolean → boolean | kleene | — | The opposite of a condition. | `!isSet(due)` |
| L4 | `?:` (cond) | boolean × τ × τ → τ (option if an arm is) | total | overflow | The first value when the condition is true, else the second. | `isSet(due) ? due : today()` |
| L5 | `??` (binary) | option<τ> × τ → τ | total | overflow | The value, or a fallback when it is blank. | `due ?? today()` |
| L6 | `isBlank` (call) | any → boolean | total | — | True when a value is blank. | `isBlank(due)` |
| L7 | `isSet` (call) | any → boolean | total | — | True when a value is set. | `isSet(due)` |

## compare {#compare}

| Row | Spelling | Signature | NULL rule | Faults | Summary | Example |
|---|---|---|---|---|---|---|
| C1 | `==` (binary) | integer == integer → boolean | fault | overflow | True when two values are equal (==) or differ (!=). | `status != 'paid'` |
| C1 | `==` (binary) | integer == decimal → boolean | fault | overflow | True when two values are equal (==) or differ (!=). | `status != 'paid'` |
| C1 | `==` (binary) | decimal == integer → boolean | fault | overflow | True when two values are equal (==) or differ (!=). | `status != 'paid'` |
| C1 | `==` (binary) | decimal == decimal → boolean | fault | overflow | True when two values are equal (==) or differ (!=). | `status != 'paid'` |
| C1 | `==` (binary) | quantity == quantity → boolean | fault | overflow | True when two values are equal (==) or differ (!=). | `status != 'paid'` |
| C1 | `==` (binary) | money == money → boolean | fault | overflow | True when two values are equal (==) or differ (!=). | `status != 'paid'` |
| C1 | `==` (binary) | duration == duration → boolean | fault | overflow | True when two values are equal (==) or differ (!=). | `status != 'paid'` |
| C1 | `==` (binary) | text == text → boolean | fault | overflow | True when two values are equal (==) or differ (!=). | `status != 'paid'` |
| C1 | `==` (binary) | boolean == boolean → boolean | fault | overflow | True when two values are equal (==) or differ (!=). | `status != 'paid'` |
| C1 | `==` (binary) | date == date → boolean | fault | overflow | True when two values are equal (==) or differ (!=). | `status != 'paid'` |
| C1 | `==` (binary) | time == time → boolean | fault | overflow | True when two values are equal (==) or differ (!=). | `status != 'paid'` |
| C1 | `==` (binary) | instant == instant → boolean | fault | overflow | True when two values are equal (==) or differ (!=). | `status != 'paid'` |
| C1 | `==` (binary) | enum == enum → boolean | fault | overflow | True when two values are equal (==) or differ (!=). | `status != 'paid'` |
| C1 | `==` (binary) | set == set → boolean | fault | overflow | True when two values are equal (==) or differ (!=). | `status != 'paid'` |
| C1 | `!=` (binary) | integer != integer → boolean | fault | overflow | True when two values are equal (==) or differ (!=). | `status != 'paid'` |
| C1 | `!=` (binary) | integer != decimal → boolean | fault | overflow | True when two values are equal (==) or differ (!=). | `status != 'paid'` |
| C1 | `!=` (binary) | decimal != integer → boolean | fault | overflow | True when two values are equal (==) or differ (!=). | `status != 'paid'` |
| C1 | `!=` (binary) | decimal != decimal → boolean | fault | overflow | True when two values are equal (==) or differ (!=). | `status != 'paid'` |
| C1 | `!=` (binary) | quantity != quantity → boolean | fault | overflow | True when two values are equal (==) or differ (!=). | `status != 'paid'` |
| C1 | `!=` (binary) | money != money → boolean | fault | overflow | True when two values are equal (==) or differ (!=). | `status != 'paid'` |
| C1 | `!=` (binary) | duration != duration → boolean | fault | overflow | True when two values are equal (==) or differ (!=). | `status != 'paid'` |
| C1 | `!=` (binary) | text != text → boolean | fault | overflow | True when two values are equal (==) or differ (!=). | `status != 'paid'` |
| C1 | `!=` (binary) | boolean != boolean → boolean | fault | overflow | True when two values are equal (==) or differ (!=). | `status != 'paid'` |
| C1 | `!=` (binary) | date != date → boolean | fault | overflow | True when two values are equal (==) or differ (!=). | `status != 'paid'` |
| C1 | `!=` (binary) | time != time → boolean | fault | overflow | True when two values are equal (==) or differ (!=). | `status != 'paid'` |
| C1 | `!=` (binary) | instant != instant → boolean | fault | overflow | True when two values are equal (==) or differ (!=). | `status != 'paid'` |
| C1 | `!=` (binary) | enum != enum → boolean | fault | overflow | True when two values are equal (==) or differ (!=). | `status != 'paid'` |
| C1 | `!=` (binary) | set != set → boolean | fault | overflow | True when two values are equal (==) or differ (!=). | `status != 'paid'` |
| C2 | `<` (binary) | integer < integer → boolean | fault | overflow | Compares the order of two values: less or greater than. | `due < today()` |
| C2 | `<` (binary) | integer < decimal → boolean | fault | overflow | Compares the order of two values: less or greater than. | `due < today()` |
| C2 | `<` (binary) | decimal < integer → boolean | fault | overflow | Compares the order of two values: less or greater than. | `due < today()` |
| C2 | `<` (binary) | decimal < decimal → boolean | fault | overflow | Compares the order of two values: less or greater than. | `due < today()` |
| C2 | `<` (binary) | quantity < quantity → boolean | fault | overflow | Compares the order of two values: less or greater than. | `due < today()` |
| C2 | `<` (binary) | money < money → boolean | fault | overflow | Compares the order of two values: less or greater than. | `due < today()` |
| C2 | `<` (binary) | duration < duration → boolean | fault | overflow | Compares the order of two values: less or greater than. | `due < today()` |
| C2 | `<` (binary) | date < date → boolean | fault | overflow | Compares the order of two values: less or greater than. | `due < today()` |
| C2 | `<` (binary) | time < time → boolean | fault | overflow | Compares the order of two values: less or greater than. | `due < today()` |
| C2 | `<` (binary) | instant < instant → boolean | fault | overflow | Compares the order of two values: less or greater than. | `due < today()` |
| C2 | `<` (binary) | text < text → boolean | fault | overflow | Compares the order of two values: less or greater than. | `due < today()` |
| C2 | `<=` (binary) | integer <= integer → boolean | fault | overflow | Compares the order of two values: less or greater than. | `due < today()` |
| C2 | `<=` (binary) | integer <= decimal → boolean | fault | overflow | Compares the order of two values: less or greater than. | `due < today()` |
| C2 | `<=` (binary) | decimal <= integer → boolean | fault | overflow | Compares the order of two values: less or greater than. | `due < today()` |
| C2 | `<=` (binary) | decimal <= decimal → boolean | fault | overflow | Compares the order of two values: less or greater than. | `due < today()` |
| C2 | `<=` (binary) | quantity <= quantity → boolean | fault | overflow | Compares the order of two values: less or greater than. | `due < today()` |
| C2 | `<=` (binary) | money <= money → boolean | fault | overflow | Compares the order of two values: less or greater than. | `due < today()` |
| C2 | `<=` (binary) | duration <= duration → boolean | fault | overflow | Compares the order of two values: less or greater than. | `due < today()` |
| C2 | `<=` (binary) | date <= date → boolean | fault | overflow | Compares the order of two values: less or greater than. | `due < today()` |
| C2 | `<=` (binary) | time <= time → boolean | fault | overflow | Compares the order of two values: less or greater than. | `due < today()` |
| C2 | `<=` (binary) | instant <= instant → boolean | fault | overflow | Compares the order of two values: less or greater than. | `due < today()` |
| C2 | `<=` (binary) | text <= text → boolean | fault | overflow | Compares the order of two values: less or greater than. | `due < today()` |
| C2 | `>` (binary) | integer > integer → boolean | fault | overflow | Compares the order of two values: less or greater than. | `due < today()` |
| C2 | `>` (binary) | integer > decimal → boolean | fault | overflow | Compares the order of two values: less or greater than. | `due < today()` |
| C2 | `>` (binary) | decimal > integer → boolean | fault | overflow | Compares the order of two values: less or greater than. | `due < today()` |
| C2 | `>` (binary) | decimal > decimal → boolean | fault | overflow | Compares the order of two values: less or greater than. | `due < today()` |
| C2 | `>` (binary) | quantity > quantity → boolean | fault | overflow | Compares the order of two values: less or greater than. | `due < today()` |
| C2 | `>` (binary) | money > money → boolean | fault | overflow | Compares the order of two values: less or greater than. | `due < today()` |
| C2 | `>` (binary) | duration > duration → boolean | fault | overflow | Compares the order of two values: less or greater than. | `due < today()` |
| C2 | `>` (binary) | date > date → boolean | fault | overflow | Compares the order of two values: less or greater than. | `due < today()` |
| C2 | `>` (binary) | time > time → boolean | fault | overflow | Compares the order of two values: less or greater than. | `due < today()` |
| C2 | `>` (binary) | instant > instant → boolean | fault | overflow | Compares the order of two values: less or greater than. | `due < today()` |
| C2 | `>` (binary) | text > text → boolean | fault | overflow | Compares the order of two values: less or greater than. | `due < today()` |
| C2 | `>=` (binary) | integer >= integer → boolean | fault | overflow | Compares the order of two values: less or greater than. | `due < today()` |
| C2 | `>=` (binary) | integer >= decimal → boolean | fault | overflow | Compares the order of two values: less or greater than. | `due < today()` |
| C2 | `>=` (binary) | decimal >= integer → boolean | fault | overflow | Compares the order of two values: less or greater than. | `due < today()` |
| C2 | `>=` (binary) | decimal >= decimal → boolean | fault | overflow | Compares the order of two values: less or greater than. | `due < today()` |
| C2 | `>=` (binary) | quantity >= quantity → boolean | fault | overflow | Compares the order of two values: less or greater than. | `due < today()` |
| C2 | `>=` (binary) | money >= money → boolean | fault | overflow | Compares the order of two values: less or greater than. | `due < today()` |
| C2 | `>=` (binary) | duration >= duration → boolean | fault | overflow | Compares the order of two values: less or greater than. | `due < today()` |
| C2 | `>=` (binary) | date >= date → boolean | fault | overflow | Compares the order of two values: less or greater than. | `due < today()` |
| C2 | `>=` (binary) | time >= time → boolean | fault | overflow | Compares the order of two values: less or greater than. | `due < today()` |
| C2 | `>=` (binary) | instant >= instant → boolean | fault | overflow | Compares the order of two values: less or greater than. | `due < today()` |
| C2 | `>=` (binary) | text >= text → boolean | fault | overflow | Compares the order of two values: less or greater than. | `due < today()` |
| C3 | `in` (binary) | integer in [integer…] → boolean (empty list → false) | kleene | overflow | True when a value is one of a list. | `status in ['sent', 'paid']` |
| C3 | `in` (binary) | decimal in [decimal…] → boolean (empty list → false) | kleene | overflow | True when a value is one of a list. | `status in ['sent', 'paid']` |
| C3 | `in` (binary) | quantity in [quantity…] → boolean (empty list → false) | kleene | overflow | True when a value is one of a list. | `status in ['sent', 'paid']` |
| C3 | `in` (binary) | money in [money…] → boolean (empty list → false) | kleene | overflow | True when a value is one of a list. | `status in ['sent', 'paid']` |
| C3 | `in` (binary) | duration in [duration…] → boolean (empty list → false) | kleene | overflow | True when a value is one of a list. | `status in ['sent', 'paid']` |
| C3 | `in` (binary) | text in [text…] → boolean (empty list → false) | kleene | overflow | True when a value is one of a list. | `status in ['sent', 'paid']` |
| C3 | `in` (binary) | boolean in [boolean…] → boolean (empty list → false) | kleene | overflow | True when a value is one of a list. | `status in ['sent', 'paid']` |
| C3 | `in` (binary) | date in [date…] → boolean (empty list → false) | kleene | overflow | True when a value is one of a list. | `status in ['sent', 'paid']` |
| C3 | `in` (binary) | time in [time…] → boolean (empty list → false) | kleene | overflow | True when a value is one of a list. | `status in ['sent', 'paid']` |
| C3 | `in` (binary) | instant in [instant…] → boolean (empty list → false) | kleene | overflow | True when a value is one of a list. | `status in ['sent', 'paid']` |
| C3 | `in` (binary) | enum in [enum…] → boolean (empty list → false) | kleene | overflow | True when a value is one of a list. | `status in ['sent', 'paid']` |
| C4 | `in` (binary) | enum<E> in set<E> → boolean | strict | — | True when an enum value is in a set. | `'finance' in me.groups` |
| C5 | `in` (binary) | date in period → boolean | strict | — | True when a date falls within a period. | `due in weekOf(today())` |
| C6 | `hasAny` (method) | set<E>.hasAny([enum<E>…]) → boolean | total | — | True when a set holds any, or all, of the given values. | `me.groups.hasAny(['sales', 'finance'])` |
| C6 | `hasAny` (method) | set<E>.hasAny(set<E>) → boolean | total | — | True when a set holds any, or all, of the given values. | `me.groups.hasAny(['sales', 'finance'])` |
| C6 | `hasAll` (method) | set<E>.hasAll([enum<E>…]) → boolean | total | — | True when a set holds any, or all, of the given values. | `me.groups.hasAny(['sales', 'finance'])` |
| C6 | `hasAll` (method) | set<E>.hasAll(set<E>) → boolean | total | — | True when a set holds any, or all, of the given values. | `me.groups.hasAny(['sales', 'finance'])` |
| C7 | `count` (method) | set<E>.count() → integer | total | — | The number of values in a set. | `me.groups.count()` |

## arith {#arith}

| Row | Spelling | Signature | NULL rule | Faults | Summary | Example |
|---|---|---|---|---|---|---|
| A1 | `-` (unary) | -integer → integer | fault | overflow | A number with its sign flipped. | `-total` |
| A1 | `-` (unary) | -decimal → decimal | fault | overflow | A number with its sign flipped. | `-total` |
| A1 | `-` (unary) | -quantity → quantity | fault | overflow | A number with its sign flipped. | `-total` |
| A1 | `-` (unary) | -money → money | fault | overflow | A number with its sign flipped. | `-total` |
| A1 | `-` (unary) | -duration → duration | fault | overflow | A number with its sign flipped. | `-total` |
| A2 | `+` (binary) | integer + integer → integer | fault | overflow, out_of_range | Adds or subtracts numbers, money, quantities or durations; moves an instant by a duration, or a time of day round the clock. | `subtotal + tax` |
| A2 | `+` (binary) | integer + decimal<sb> → decimal<max(sa, sb)> | fault | overflow, out_of_range | Adds or subtracts numbers, money, quantities or durations; moves an instant by a duration, or a time of day round the clock. | `subtotal + tax` |
| A2 | `+` (binary) | decimal<sa> + integer → decimal<max(sa, sb)> | fault | overflow, out_of_range | Adds or subtracts numbers, money, quantities or durations; moves an instant by a duration, or a time of day round the clock. | `subtotal + tax` |
| A2 | `+` (binary) | decimal<sa> + decimal<sb> → decimal<max(sa, sb)> | fault | overflow, out_of_range | Adds or subtracts numbers, money, quantities or durations; moves an instant by a duration, or a time of day round the clock. | `subtotal + tax` |
| A2 | `+` (binary) | quantity<u, sa> + quantity<u, sb> → quantity<u, max(sa, sb)> | fault | overflow, out_of_range | Adds or subtracts numbers, money, quantities or durations; moves an instant by a duration, or a time of day round the clock. | `subtotal + tax` |
| A2 | `+` (binary) | money<c> + money<c> → money<c> | fault | overflow, out_of_range | Adds or subtracts numbers, money, quantities or durations; moves an instant by a duration, or a time of day round the clock. | `subtotal + tax` |
| A2 | `+` (binary) | duration + duration → duration | fault | overflow, out_of_range | Adds or subtracts numbers, money, quantities or durations; moves an instant by a duration, or a time of day round the clock. | `subtotal + tax` |
| A2 | `-` (binary) | integer - integer → integer | fault | overflow, out_of_range | Adds or subtracts numbers, money, quantities or durations; moves an instant by a duration, or a time of day round the clock. | `subtotal + tax` |
| A2 | `-` (binary) | integer - decimal<sb> → decimal<max(sa, sb)> | fault | overflow, out_of_range | Adds or subtracts numbers, money, quantities or durations; moves an instant by a duration, or a time of day round the clock. | `subtotal + tax` |
| A2 | `-` (binary) | decimal<sa> - integer → decimal<max(sa, sb)> | fault | overflow, out_of_range | Adds or subtracts numbers, money, quantities or durations; moves an instant by a duration, or a time of day round the clock. | `subtotal + tax` |
| A2 | `-` (binary) | decimal<sa> - decimal<sb> → decimal<max(sa, sb)> | fault | overflow, out_of_range | Adds or subtracts numbers, money, quantities or durations; moves an instant by a duration, or a time of day round the clock. | `subtotal + tax` |
| A2 | `-` (binary) | quantity<u, sa> - quantity<u, sb> → quantity<u, max(sa, sb)> | fault | overflow, out_of_range | Adds or subtracts numbers, money, quantities or durations; moves an instant by a duration, or a time of day round the clock. | `subtotal + tax` |
| A2 | `-` (binary) | money<c> - money<c> → money<c> | fault | overflow, out_of_range | Adds or subtracts numbers, money, quantities or durations; moves an instant by a duration, or a time of day round the clock. | `subtotal + tax` |
| A2 | `-` (binary) | duration - duration → duration | fault | overflow, out_of_range | Adds or subtracts numbers, money, quantities or durations; moves an instant by a duration, or a time of day round the clock. | `subtotal + tax` |
| A2 | `+` (binary) | instant + duration → instant (elapsed ms) | fault | overflow, out_of_range | Adds or subtracts numbers, money, quantities or durations; moves an instant by a duration, or a time of day round the clock. | `subtotal + tax` |
| A2 | `-` (binary) | instant − duration → instant (elapsed ms) | fault | overflow, out_of_range | Adds or subtracts numbers, money, quantities or durations; moves an instant by a duration, or a time of day round the clock. | `subtotal + tax` |
| A2 | `+` (binary) | time + duration (whole minutes) → time (modulo 24 h) | fault | overflow, out_of_range | Adds or subtracts numbers, money, quantities or durations; moves an instant by a duration, or a time of day round the clock. | `subtotal + tax` |
| A2 | `-` (binary) | time − duration (whole minutes) → time (modulo 24 h) | fault | overflow, out_of_range | Adds or subtracts numbers, money, quantities or durations; moves an instant by a duration, or a time of day round the clock. | `subtotal + tax` |
| A3 | `-` (binary) | date − date → integer (days) | strict | — | The number of days between two dates. | `due - date('2026-01-01')` |
| A4 | `-` (binary) | instant − instant → duration (ms) | strict | — | The duration between two instants or two times. | `now() - created` |
| A4 | `-` (binary) | time − time → duration (the wall-clock minutes, in ms) | strict | — | The duration between two instants or two times. | `now() - created` |
| A5 | `*` (binary) | integer × integer → integer | fault | overflow | Multiplies numbers, or scales money, a quantity or a duration. | `qty * price` |
| A5 | `*` (binary) | integer × decimal → decimal<sa + sb> | fault | overflow | Multiplies numbers, or scales money, a quantity or a duration. | `qty * price` |
| A5 | `*` (binary) | decimal × integer → decimal<sa + sb> | fault | overflow | Multiplies numbers, or scales money, a quantity or a duration. | `qty * price` |
| A5 | `*` (binary) | decimal × decimal → decimal<sa + sb> | fault | overflow | Multiplies numbers, or scales money, a quantity or a duration. | `qty * price` |
| A5 | `*` (binary) | quantity × integer → quantity<u, sa + sb> | fault | overflow | Multiplies numbers, or scales money, a quantity or a duration. | `qty * price` |
| A5 | `*` (binary) | quantity × decimal → quantity<u, sa + sb> | fault | overflow | Multiplies numbers, or scales money, a quantity or a duration. | `qty * price` |
| A5 | `*` (binary) | integer × quantity → quantity<u, sa + sb> | fault | overflow | Multiplies numbers, or scales money, a quantity or a duration. | `qty * price` |
| A5 | `*` (binary) | decimal × quantity → quantity<u, sa + sb> | fault | overflow | Multiplies numbers, or scales money, a quantity or a duration. | `qty * price` |
| A5 | `*` (binary) | money × integer → money<c> | fault | overflow | Multiplies numbers, or scales money, a quantity or a duration. | `qty * price` |
| A5 | `*` (binary) | integer × money → money<c> | fault | overflow | Multiplies numbers, or scales money, a quantity or a duration. | `qty * price` |
| A5 | `*` (binary) | money × decimal → unrounded<money<c>> | fault | overflow | Multiplies numbers, or scales money, a quantity or a duration. | `qty * price` |
| A5 | `*` (binary) | decimal × money → unrounded<money<c>> | fault | overflow | Multiplies numbers, or scales money, a quantity or a duration. | `qty * price` |
| A5 | `*` (binary) | money × quantity → unrounded<money<c>> | fault | overflow | Multiplies numbers, or scales money, a quantity or a duration. | `qty * price` |
| A5 | `*` (binary) | quantity × money → unrounded<money<c>> | fault | overflow | Multiplies numbers, or scales money, a quantity or a duration. | `qty * price` |
| A5 | `*` (binary) | duration × integer → duration | fault | overflow | Multiplies numbers, or scales money, a quantity or a duration. | `qty * price` |
| A5 | `*` (binary) | integer × duration → duration | fault | overflow | Multiplies numbers, or scales money, a quantity or a duration. | `qty * price` |
| A6 | `/` (binary) | integer / integer → decimal<min(max(sa, sb) + 6, 12)> (half_even) | fault | div_zero, overflow | Divides one number by another, or one duration by another. | `total / qty` |
| A6 | `/` (binary) | integer / decimal → decimal<min(max(sa, sb) + 6, 12)> (half_even) | fault | div_zero, overflow | Divides one number by another, or one duration by another. | `total / qty` |
| A6 | `/` (binary) | decimal / integer → decimal<min(max(sa, sb) + 6, 12)> (half_even) | fault | div_zero, overflow | Divides one number by another, or one duration by another. | `total / qty` |
| A6 | `/` (binary) | decimal / decimal → decimal<min(max(sa, sb) + 6, 12)> (half_even) | fault | div_zero, overflow | Divides one number by another, or one duration by another. | `total / qty` |
| A6 | `/` (binary) | quantity<u, sa> / integer → quantity<u, min(max(sa, sb) + 6, 12)> | fault | div_zero, overflow | Divides one number by another, or one duration by another. | `total / qty` |
| A6 | `/` (binary) | quantity<u, sa> / decimal → quantity<u, min(max(sa, sb) + 6, 12)> | fault | div_zero, overflow | Divides one number by another, or one duration by another. | `total / qty` |
| A6 | `/` (binary) | quantity<u, sa> / quantity<u, sb> → decimal<min(max(sa, sb) + 6, 12)> | fault | div_zero, overflow | Divides one number by another, or one duration by another. | `total / qty` |
| A6 | `/` (binary) | money<c> / integer → unrounded<money<c>> | fault | div_zero, overflow | Divides one number by another, or one duration by another. | `total / qty` |
| A6 | `/` (binary) | money<c> / decimal → unrounded<money<c>> | fault | div_zero, overflow | Divides one number by another, or one duration by another. | `total / qty` |
| A6 | `/` (binary) | money<c> / money<c> → decimal<6> | fault | div_zero, overflow | Divides one number by another, or one duration by another. | `total / qty` |
| A6 | `/` (binary) | duration / duration → decimal<6> (half_even) | fault | div_zero, overflow | Divides one number by another, or one duration by another. | `total / qty` |
| A7 | `%` (binary) | integer % integer → integer (sign of the dividend) | fault | div_zero | The remainder of a whole-number division. | `qty % 12` |
| A8 | `div` (call) | div(integer, integer) → integer (toward zero) | fault | div_zero, overflow | Whole-number division, rounded toward zero. | `div(qty, 12)` |
| A8 | `div` (call) | div(duration, duration) → integer (toward zero) | fault | div_zero, overflow | Whole-number division, rounded toward zero. | `div(qty, 12)` |
| A10 | `round` (call) | round(decimal<sx> (or a `/` or `avg` node, fused), s, mode) → decimal<s> | fault | overflow | Rounds a number to a given number of decimals. | `round(total / qty, 2, 'half_even')` |
| A10 | `round` (call) | round(quantity<u, sx> (or a `/` node, fused), s, mode) → quantity<u, s> | fault | overflow | Rounds a number to a given number of decimals. | `round(total / qty, 2, 'half_even')` |
| A11 | `abs` (call) | abs(integer) → integer | fault | overflow | The absolute value of a number. | `abs(balance)` |
| A11 | `abs` (call) | abs(decimal) → decimal | fault | overflow | The absolute value of a number. | `abs(balance)` |
| A11 | `abs` (call) | abs(quantity) → quantity | fault | overflow | The absolute value of a number. | `abs(balance)` |
| A11 | `abs` (call) | abs(money) → money | fault | overflow | The absolute value of a number. | `abs(balance)` |
| A11 | `abs` (call) | abs(duration) → duration | fault | overflow | The absolute value of a number. | `abs(balance)` |
| A12 | `min` (call) | min(τ, τ, …) → τ (one ordered type; numbers scale-aligned) | fault | overflow | The smallest or largest of two or more values. | `max(due, today())` |
| A12 | `max` (call) | max(τ, τ, …) → τ (one ordered type; numbers scale-aligned) | fault | overflow | The smallest or largest of two or more values. | `max(due, today())` |
| A13 | `percent` (call) | percent(integer, integer) → quantity<percent, 2> (half_even) | fault | div_zero, overflow | One number as a percentage of another. | `percent(paid, total)` |
| A13 | `percent` (call) | percent(integer, decimal) → quantity<percent, 2> (half_even) | fault | div_zero, overflow | One number as a percentage of another. | `percent(paid, total)` |
| A13 | `percent` (call) | percent(decimal, integer) → quantity<percent, 2> (half_even) | fault | div_zero, overflow | One number as a percentage of another. | `percent(paid, total)` |
| A13 | `percent` (call) | percent(decimal, decimal) → quantity<percent, 2> (half_even) | fault | div_zero, overflow | One number as a percentage of another. | `percent(paid, total)` |
| A13 | `percent` (call) | percent(quantity, quantity) → quantity<percent, 2> (half_even) | fault | div_zero, overflow | One number as a percentage of another. | `percent(paid, total)` |
| A13 | `percent` (call) | percent(money, money) → quantity<percent, 2> (half_even) | fault | div_zero, overflow | One number as a percentage of another. | `percent(paid, total)` |
| A13 | `percent` (call) | percent(duration, duration) → quantity<percent, 2> (half_even) | fault | div_zero, overflow | One number as a percentage of another. | `percent(paid, total)` |
| A15 | `quantity` (call) | quantity(integer, unit literal) → quantity<unit, 0> | strict | — | A quantity in a unit. | `quantity(2.5, 'kg')` |
| A15 | `quantity` (call) | quantity(decimal<s>, unit literal) → quantity<unit, s> | strict | — | A quantity in a unit. | `quantity(2.5, 'kg')` |
| A16 | `duration` (call) | duration(integer, 'ms' \| 's' \| 'min' \| 'h') → duration | fault | overflow | A duration from a number and a unit. | `duration(90, 'min')` |
| A17 | `amount` (call) | amount(quantity<u, s>, unit literal: u or a smaller unit of u's dimension) → integer (s = 0) / decimal<s> | fault | overflow | The number of a quantity in a unit. | `amount(break_length, 'min')` |

## money {#money}

| Row | Spelling | Signature | NULL rule | Faults | Summary | Example |
|---|---|---|---|---|---|---|
| A9 | `round` (call) | round(money<c>, mode) → money<c> | fault | overflow | Rounds money to its currency’s minor unit. | `round(price * 0.25, 'half_even')` |
| A9 | `round` (call) | round(unrounded<money<c>> (a `*`, `/` or `avg` node), mode) → money<c> | fault | overflow | Rounds money to its currency’s minor unit. | `round(price * 0.25, 'half_even')` |
| A14 | `money` (call) | money(integer, currency literal or path) → money<cur> (minor units) | fault | overflow, out_of_range | A money amount in a currency. | `money(12.50, 'DKK')` |
| A14 | `money` (call) | money(decimal<s ≤ e>, currency literal or path) → money<cur> (minor units) | fault | overflow, out_of_range | A money amount in a currency. | `money(12.50, 'DKK')` |

## text {#text}

| Row | Spelling | Signature | NULL rule | Faults | Summary | Example |
|---|---|---|---|---|---|---|
| T1 | `concat` (call) | text × … → text (blank is empty) | total | — | Joins texts into one. | `concat(customer.name, ' – ', number)` |
| T2 | `length` (call) | text → integer (code points) | strict | — | The number of characters in a text. | `length(number)` |
| T3 | `contains` (call) | text × text → boolean (exact) | strict | — | True when a text contains another text. | `contains(number, 'INV')` |
| T4 | `startsWith` (call) | text × text → boolean (exact) | strict | — | True when a text starts with another text. | `startsWith(number, 'INV-')` |
| T5 | `endsWith` (call) | text × text → boolean (exact) | strict | — | True when a text ends with another text. | `endsWith(file_name, '.pdf')` |

## date {#date}

| Row | Spelling | Signature | NULL rule | Faults | Summary | Example |
|---|---|---|---|---|---|---|
| D1 | `today` (call) | today() → date (the org day of the request clock) | strict | — | Today’s date in the organization’s zone. | `due < today()` |
| D2 | `now` (call) | now() → instant (the request clock) | strict | — | The current instant. | `now() - created` |
| D4 | `addDays` (call) | addDays(date, integer) → date | fault | out_of_range | A date plus a number of days. | `addDays(due, 14)` |
| D5 | `addMonths` (call) | addMonths(date, integer) → date (clamped to the month end) | fault | out_of_range | A date plus a number of months, kept within the month. | `addMonths(start, 1)` |
| D6 | `weekday` (call) | weekday(date) → integer (1 Monday … 7 Sunday, ISO) | strict | — | The weekday, year, month or day of a date. | `weekday(due) <= 5` |
| D6 | `year` (call) | year(date) → integer | strict | — | The weekday, year, month or day of a date. | `weekday(due) <= 5` |
| D6 | `month` (call) | month(date) → integer (1–12) | strict | — | The weekday, year, month or day of a date. | `weekday(due) <= 5` |
| D6 | `day` (call) | day(date) → integer (1–31) | strict | — | The weekday, year, month or day of a date. | `weekday(due) <= 5` |
| D7 | `hour` (call) | hour(time) → integer (0–23) | strict | — | The hour or minute of a time. | `hour(opens) < 9` |
| D7 | `minute` (call) | minute(time) → integer (0–59) | strict | — | The hour or minute of a time. | `hour(opens) < 9` |
| D8 | `dateOf` (call) | dateOf(instant) → date (the org zone) | fault | out_of_range | The date or time of an instant in the organization’s zone. | `dateOf(created) == today()` |
| D8 | `timeOf` (call) | timeOf(instant) → time (the org zone, to the minute) | fault | out_of_range | The date or time of an instant in the organization’s zone. | `dateOf(created) == today()` |
| D9 | `at` (call) | at(date, time) → instant (the org zone; a DST gap is unknown, an overlap the earlier) | fault | dst_gap, out_of_range | The instant of a date and time in the organization’s zone. | `at(due, time('17:00'))` |
| D10 | `period` (call) | period(date, date) → period (start ≤ end) | fault | out_of_range | The week or month around a date, or the period between two dates. | `due in weekOf(today())` |
| D10 | `weekOf` (call) | weekOf(date) → period (the ISO week, Monday–Sunday) | fault | out_of_range | The week or month around a date, or the period between two dates. | `due in weekOf(today())` |
| D10 | `monthOf` (call) | monthOf(date) → period (the calendar month) | fault | out_of_range | The week or month around a date, or the period between two dates. | `due in weekOf(today())` |
| D11 | `start` (member) | p.start → date | strict | — | The first or last date of a period. | `weekOf(today()).start` |
| D11 | `end` (member) | p.end → date | strict | — | The first or last date of a period. | `weekOf(today()).start` |

## series {#series}

| Row | Spelling | Signature | NULL rule | Faults | Summary | Example |
|---|---|---|---|---|---|---|
| S1 | `days` (call) | days(date, date) → collection<date> (inclusive; a > b is unknown) | fault | series_too_long, out_of_range | Every date in a period. | `days(start, end).count()` |
| S1 | `days` (call) | days(period) → collection<date> | fault | series_too_long, out_of_range | Every date in a period. | `days(start, end).count()` |
| S2 | `weeks` (call) | weeks(period) → collection<period> (the ISO weeks it touches) | fault | series_too_long, out_of_range | Every week or month in a period. | `weeks(monthOf(today())).count()` |
| S2 | `months` (call) | months(period) → collection<period> (the calendar months it touches) | fault | series_too_long, out_of_range | Every week or month in a period. | `weeks(monthOf(today())).count()` |
| S3 | `hours` (call) | hours(date) → collection<instant> (the org day: 23, 24 or 25) | fault | out_of_range | Every hour of a date in the organization’s zone. | `hours(today()).count()` |

## macro {#macro}

| Row | Spelling | Signature | NULL rule | Faults | Summary | Example |
|---|---|---|---|---|---|---|
| M1 | `where` (macro) | collection<τ>.where(x => boolean) → collection<τ> | total | — | The elements for which a condition is true. | `lines.where(l => l.status == 'open')` |
| M2 | `count` (method) | collection<τ>.count() → integer | total | — | The number of elements, or of those for which a condition is true. | `lines.count(l => l.qty > 0)` |
| M2 | `count` (method) | collection<τ>.count(x => boolean) → integer | total | — | The number of elements, or of those for which a condition is true. | `lines.count(l => l.qty > 0)` |
| M3 | `sum` (macro) | collection<τ>.sum(x => integer) → integer (empty → 0) | total | overflow | The sum of a value over the elements. | `lines.sum(l => l.amount)` |
| M3 | `sum` (macro) | collection<τ>.sum(x => decimal<s>) → decimal<s> (empty → 0) | total | overflow | The sum of a value over the elements. | `lines.sum(l => l.amount)` |
| M3 | `sum` (macro) | collection<τ>.sum(x => quantity) → quantity (empty → 0) | total | overflow | The sum of a value over the elements. | `lines.sum(l => l.amount)` |
| M3 | `sum` (macro) | collection<τ>.sum(x => money) → money (empty → 0) | total | overflow | The sum of a value over the elements. | `lines.sum(l => l.amount)` |
| M3 | `sum` (macro) | collection<τ>.sum(x => duration) → duration (empty → 0) | total | overflow | The sum of a value over the elements. | `lines.sum(l => l.amount)` |
| M4 | `min` (macro) | collection<τ>.min(x => integer) → option<integer> (empty → blank) | total | — | The smallest or largest value over the elements. | `lines.max(l => l.due)` |
| M4 | `min` (macro) | collection<τ>.min(x => decimal) → option<decimal> (empty → blank) | total | — | The smallest or largest value over the elements. | `lines.max(l => l.due)` |
| M4 | `min` (macro) | collection<τ>.min(x => quantity) → option<quantity> (empty → blank) | total | — | The smallest or largest value over the elements. | `lines.max(l => l.due)` |
| M4 | `min` (macro) | collection<τ>.min(x => money) → option<money> (empty → blank) | total | — | The smallest or largest value over the elements. | `lines.max(l => l.due)` |
| M4 | `min` (macro) | collection<τ>.min(x => date) → option<date> (empty → blank) | total | — | The smallest or largest value over the elements. | `lines.max(l => l.due)` |
| M4 | `min` (macro) | collection<τ>.min(x => time) → option<time> (empty → blank) | total | — | The smallest or largest value over the elements. | `lines.max(l => l.due)` |
| M4 | `min` (macro) | collection<τ>.min(x => instant) → option<instant> (empty → blank) | total | — | The smallest or largest value over the elements. | `lines.max(l => l.due)` |
| M4 | `min` (macro) | collection<τ>.min(x => duration) → option<duration> (empty → blank) | total | — | The smallest or largest value over the elements. | `lines.max(l => l.due)` |
| M4 | `min` (macro) | collection<τ>.min(x => text) → option<text> (empty → blank) | total | — | The smallest or largest value over the elements. | `lines.max(l => l.due)` |
| M4 | `max` (macro) | collection<τ>.max(x => integer) → option<integer> (empty → blank) | total | — | The smallest or largest value over the elements. | `lines.max(l => l.due)` |
| M4 | `max` (macro) | collection<τ>.max(x => decimal) → option<decimal> (empty → blank) | total | — | The smallest or largest value over the elements. | `lines.max(l => l.due)` |
| M4 | `max` (macro) | collection<τ>.max(x => quantity) → option<quantity> (empty → blank) | total | — | The smallest or largest value over the elements. | `lines.max(l => l.due)` |
| M4 | `max` (macro) | collection<τ>.max(x => money) → option<money> (empty → blank) | total | — | The smallest or largest value over the elements. | `lines.max(l => l.due)` |
| M4 | `max` (macro) | collection<τ>.max(x => date) → option<date> (empty → blank) | total | — | The smallest or largest value over the elements. | `lines.max(l => l.due)` |
| M4 | `max` (macro) | collection<τ>.max(x => time) → option<time> (empty → blank) | total | — | The smallest or largest value over the elements. | `lines.max(l => l.due)` |
| M4 | `max` (macro) | collection<τ>.max(x => instant) → option<instant> (empty → blank) | total | — | The smallest or largest value over the elements. | `lines.max(l => l.due)` |
| M4 | `max` (macro) | collection<τ>.max(x => duration) → option<duration> (empty → blank) | total | — | The smallest or largest value over the elements. | `lines.max(l => l.due)` |
| M4 | `max` (macro) | collection<τ>.max(x => text) → option<text> (empty → blank) | total | — | The smallest or largest value over the elements. | `lines.max(l => l.due)` |
| M5 | `avg` (macro) | collection<τ>.avg(x => integer) → option<decimal<min(s + 6, 12)>> | total | overflow | The average of a value over the elements. | `lines.avg(l => l.qty)` |
| M5 | `avg` (macro) | collection<τ>.avg(x => decimal<s>) → option<decimal<min(s + 6, 12)>> | total | overflow | The average of a value over the elements. | `lines.avg(l => l.qty)` |
| M5 | `avg` (macro) | collection<τ>.avg(x => money<c>) → option<unrounded<money<c>>> (minor units at scale 6) | total | overflow | The average of a value over the elements. | `lines.avg(l => l.qty)` |
| M6 | `any` (macro) | collection<τ>.any() → boolean (not empty) | total | — | True when there is an element, or one for which a condition is true. | `lines.any(l => isBlank(l.note))` |
| M6 | `any` (macro) | collection<τ>.any(x => boolean) → boolean | total | — | True when there is an element, or one for which a condition is true. | `lines.any(l => isBlank(l.note))` |
| M7 | `all` (macro) | collection<τ>.all(x => boolean) → boolean (unknown fails; empty → true) | total | — | True when a condition is true for every element. | `lines.all(l => l.qty > 0)` |
| M8 | `only` (macro) | collection<τ>.only() → option<τ> (empty → blank; two or more → unknown(not_unique)) | fault | not_unique | The one element, when there is exactly one. | `unit.tenants.only()` |
| M9 | `first` (macro) | collection<τ>.first(x => integer) → option<τ> (by key, then identity; blank keys skipped; empty → blank) | total | — | The element with the lowest or highest key. | `invoices.last(i => i.received_on)` |
| M9 | `first` (macro) | collection<τ>.first(x => decimal) → option<τ> (by key, then identity; blank keys skipped; empty → blank) | total | — | The element with the lowest or highest key. | `invoices.last(i => i.received_on)` |
| M9 | `first` (macro) | collection<τ>.first(x => quantity) → option<τ> (by key, then identity; blank keys skipped; empty → blank) | total | — | The element with the lowest or highest key. | `invoices.last(i => i.received_on)` |
| M9 | `first` (macro) | collection<τ>.first(x => money) → option<τ> (by key, then identity; blank keys skipped; empty → blank) | total | — | The element with the lowest or highest key. | `invoices.last(i => i.received_on)` |
| M9 | `first` (macro) | collection<τ>.first(x => date) → option<τ> (by key, then identity; blank keys skipped; empty → blank) | total | — | The element with the lowest or highest key. | `invoices.last(i => i.received_on)` |
| M9 | `first` (macro) | collection<τ>.first(x => time) → option<τ> (by key, then identity; blank keys skipped; empty → blank) | total | — | The element with the lowest or highest key. | `invoices.last(i => i.received_on)` |
| M9 | `first` (macro) | collection<τ>.first(x => instant) → option<τ> (by key, then identity; blank keys skipped; empty → blank) | total | — | The element with the lowest or highest key. | `invoices.last(i => i.received_on)` |
| M9 | `first` (macro) | collection<τ>.first(x => duration) → option<τ> (by key, then identity; blank keys skipped; empty → blank) | total | — | The element with the lowest or highest key. | `invoices.last(i => i.received_on)` |
| M9 | `first` (macro) | collection<τ>.first(x => text) → option<τ> (by key, then identity; blank keys skipped; empty → blank) | total | — | The element with the lowest or highest key. | `invoices.last(i => i.received_on)` |
| M9 | `last` (macro) | collection<τ>.last(x => integer) → option<τ> (by key, then identity; blank keys skipped; empty → blank) | total | — | The element with the lowest or highest key. | `invoices.last(i => i.received_on)` |
| M9 | `last` (macro) | collection<τ>.last(x => decimal) → option<τ> (by key, then identity; blank keys skipped; empty → blank) | total | — | The element with the lowest or highest key. | `invoices.last(i => i.received_on)` |
| M9 | `last` (macro) | collection<τ>.last(x => quantity) → option<τ> (by key, then identity; blank keys skipped; empty → blank) | total | — | The element with the lowest or highest key. | `invoices.last(i => i.received_on)` |
| M9 | `last` (macro) | collection<τ>.last(x => money) → option<τ> (by key, then identity; blank keys skipped; empty → blank) | total | — | The element with the lowest or highest key. | `invoices.last(i => i.received_on)` |
| M9 | `last` (macro) | collection<τ>.last(x => date) → option<τ> (by key, then identity; blank keys skipped; empty → blank) | total | — | The element with the lowest or highest key. | `invoices.last(i => i.received_on)` |
| M9 | `last` (macro) | collection<τ>.last(x => time) → option<τ> (by key, then identity; blank keys skipped; empty → blank) | total | — | The element with the lowest or highest key. | `invoices.last(i => i.received_on)` |
| M9 | `last` (macro) | collection<τ>.last(x => instant) → option<τ> (by key, then identity; blank keys skipped; empty → blank) | total | — | The element with the lowest or highest key. | `invoices.last(i => i.received_on)` |
| M9 | `last` (macro) | collection<τ>.last(x => duration) → option<τ> (by key, then identity; blank keys skipped; empty → blank) | total | — | The element with the lowest or highest key. | `invoices.last(i => i.received_on)` |
| M9 | `last` (macro) | collection<τ>.last(x => text) → option<τ> (by key, then identity; blank keys skipped; empty → blank) | total | — | The element with the lowest or highest key. | `invoices.last(i => i.received_on)` |

## ref {#ref}

| Row | Spelling | Signature | NULL rule | Faults | Summary | Example |
|---|---|---|---|---|---|---|
| P3 | `==` (binary) | ref<T> == ref<T> → boolean (by id) | strict | — | True when two references point to the same record (==) or to different ones (!=). | `l.contract == this` |
| P3 | `!=` (binary) | ref<T> != ref<T> → boolean (by id) | strict | — | True when two references point to the same record (==) or to different ones (!=). | `l.contract == this` |

## path {#path}

No operators yet.
