Expressions
Rules aren't limited to just pattern matching — you can compute values in the head and filter with comparisons in the body.
Arithmetic (rule heads)
Arithmetic expressions appear in rule heads to compute derived values.
Integer operators
These work on all integer types (int8 through int64, uint8 through uint64):
| Operator | Description | Example |
|---|---|---|
+ | Addition | x + 1 |
- | Subtraction | x - y |
* | Multiplication | x * 2 |
/ | Integer division | x / 3 |
% | Modulo | x % 2 |
Heads up: expressions are parsed left-to-right without precedence. So x + y * z means (x + y) * z, not x + (y * z). When in doubt, use parentheses.
String concatenation
The cat operator glues two strings together:
| Operator | Description | Example |
|---|---|---|
cat | String concatenation | x cat y |
Examples
.decl Arc(src: int32, dst: int32, weight: int32)
.decl DoubleWeight(src: int32, dst: int32, w: int32)
.decl FullName(id: int32, full: string)
.decl Person(id: int32, first: string, last: string)
// Arithmetic in the head
DoubleWeight(x, y, w * 2) :- Arc(x, y, w).
// String concatenation in the head
FullName(id, first cat " " cat last) :- Person(id, first, last).
Comparisons (rule bodies)
Comparisons appear in rule bodies to filter tuples. They test a condition between two values:
| Operator | Description | Example |
|---|---|---|
= | Equal | x = y |
!= | Not equal | x != y |
> | Greater than | x > 0 |
< | Less than | x < 100 |
>= | Greater or equal | x >= y |
<= | Less or equal | x <= y |
Examples
// Filter: only keep arcs where weight exceeds 100
Heavy(x, y) :- Arc(x, y, w), w > 100.
// Same-generation query: pairs sharing a common ancestor, but not the same node
Sg(x, y) :- Arc(a, x), Arc(a, y), x != y.
Sg(x, y) :- Arc(a, x), Sg(a, b), Arc(b, y).