Constants
Top-level named values shared across rules
A constant is a top-level named value declared with const. Unlike a
local binding, a constant lives outside any rule and can be referenced by
every rule that follows it.
const MAX_SCORE = 100
const BLOCKED = ["spam", "abuse"]
rule Moderate {
out flagged = input.score > MAX_SCORE
out blocked = input.category in BLOCKED
}Syntax
const NAME = <expression>The name follows the usual identifier rules. The expression must be a constant expression.
Constant expressions
A constant's value is computed at compile time, so it may only use things that are known then. The following are allowed:
- Literals: numbers, strings, booleans, arrays, and objects.
- Operators (
+,&&,==,in, …) and conditionals (if/then/else,? :). - Indexing and field access on constant arrays and objects.
- References to constants declared above.
- Calls to pure built-in functions.
const LIMIT = 60 * 60 // arithmetic
const REGIONS = ["us", "eu"] // array literal
const CONFIG = { retries: 3 } // object literal
const RETRIES = CONFIG.retries // field access on a constant
const ABS = math::abs(-5) // pure built-in call
const TIER = LIMIT > 1000 ? "high" : "low"Anything that depends on runtime state is rejected:
const BAD1 = input.score // error: reads input
const BAD2 = time::now() // error: impure built-in
const BAD3 = |x| x + 1 // error: not a constant valueA constant cannot read input, call a function whose output varies at
runtime (such as time::now()), or hold a lambda or match expression.
Ordering
Constants are resolved top to bottom. A constant or rule may reference only the constants declared before it. Forward references are a compile-time error, the same as for local bindings.
const A = 10
const B = A * 2 // ok, A is declared above
rule Early { out x = C } // error: 'C' is not defined yet
const C = 5Scope
Constants are global to the file and visible to every later rule. They are fixed before any rule runs, so a constant cannot see rule-local names.
A rule may introduce a local with the same name as a constant. The local shadows the constant inside that rule:
const RATE = 1
rule Custom {
RATE = input.rate // local 'RATE' shadows the constant here
out r = RATE
}Naming
A constant name must be unique among all top-level declarations: it cannot
clash with another constant, a rule, a signal, or the reserved name input.
Runtime cost
Because constants are evaluated at compile time, referencing one has no runtime cost: the compiler folds the value into each use. A constant that no rule references is dropped and adds nothing to the compiled output.