Operators
Precedence Table
Section titled “Precedence Table”Operators are listed from highest precedence (binds tightest) to lowest.
| Precedence | Operators | Associativity | Description |
|---|---|---|---|
| 1 | . () [] ! ?? ? | Left | Member access, call, index, unwrap ops |
| 2 | not - (unary) | Right | Boolean negation, numeric negation |
| 3 | ^ | Right | Exponentiation (power) |
| 4 | * / % | Left | Multiplication, division, modulo |
| 5 | + - ++ | Left | Addition/concatenation, subtraction, concat (legacy) |
| 6 | .. ..= | None | Exclusive range, inclusive range |
| 7 | == != < > <= >= | None | Comparison (non-associative) |
| 8 | and | Left | Logical AND (short-circuit) |
| 9 | or | Left | Logical OR (short-circuit) |
| 10 | |> >> | Left | Pipe, function composition |
Detailed Reference
Section titled “Detailed Reference”Member Access, Calls, and Unwrap (. () [] ! ?? ?)
Section titled “Member Access, Calls, and Unwrap (. () [] ! ?? ?)”user.name // field accessstring.len(s) // module function callxs[0] // index readxs[i] = value // index write (var only)Unwrap operators
Section titled “Unwrap operators”Three postfix operators for unwrapping Result and Option values:
fs.read_text(path)! // unwrap or propagate error (effect fn only)int.parse(s) ?? 0 // unwrap with fallback valueint.parse(s)? // convert Result to Option (discard error)| Operator | On Result | On Option | Valid in |
|---|---|---|---|
expr! | ok(v) -> v, err(e) -> propagate | some(v) -> v, none -> propagate | effect fn only |
expr ?? fallback | ok(v) -> v, err(_) -> fallback | some(v) -> v, none -> fallback | Anywhere |
expr? | ok(v) -> some(v), err(_) -> none | Passthrough | Anywhere |
See Error Handling for detailed examples.
Unary Operators (not, -)
Section titled “Unary Operators (not, -)”not active // boolean negation-x // numeric negationThere is no boolean ! operator. Use not for boolean negation. The postfix ! is the unwrap/propagate operator.
Exponentiation (^)
Section titled “Exponentiation (^)”2 ^ 10 // => 10243.0 ^ 0.5 // => 1.732...2 ** 3 // => 8 (** is an alias for ^)Right-associative: 2 ^ 3 ^ 2 is evaluated as 2 ^ (3 ^ 2) = 2 ^ 9 = 512.
Arithmetic (* / % + -)
Section titled “Arithmetic (* / % + -)”10 * 3 // => 3010 / 3 // => 3 (integer division)10 % 3 // => 1 (modulo)5 + 3 // => 85 - 3 // => 2Concatenation (+)
Section titled “Concatenation (+)”The + operator is overloaded for strings and lists:
"hello" + " " + "world" // => "hello world"[1, 2] + [3, 4] // => [1, 2, 3, 4]Range (.. ..=)
Section titled “Range (.. ..=)”0..5 // [0, 1, 2, 3, 4] (exclusive end)1..=5 // [1, 2, 3, 4, 5] (inclusive end)for i in 0..n { ... } // optimized: no list allocationRanges are non-associative — you cannot chain them.
Comparison (== != < > <= >=)
Section titled “Comparison (== != < > <= >=)”x == y // deep equalityx != y // not equala < b // less thana > b // greater thana <= b // less than or equala >= b // greater than or equalComparison operators are non-associative: a < b < c is a compile error. Write a < b and b < c instead.
Deep equality works on all value types (records, variants, lists, maps). Function types do not support ==.
Logical (and or)
Section titled “Logical (and or)”a > 0 and b > 0 // short-circuit ANDx == 0 or y == 0 // short-circuit ORThere are no && or || operators. Use and and or.
Pipe (|>)
Section titled “Pipe (|>)”text |> string.trim |> string.split(",")
// with placeholder:xs |> filter(_, (x) => x > 0) // _ = placeholder for piped valueThe pipe operator passes the left-hand value as the first argument to the right-hand function. Use _ as a placeholder to control argument position.
Function Composition (>>)
Section titled “Function Composition (>>)”let transform = string.trim >> string.to_uppertransform(" hello ") // => "HELLO"Composes two functions left-to-right: (f >> g)(x) is equivalent to g(f(x)).
Special Operators
Section titled “Special Operators”Spread (...)
Section titled “Spread (...)”Used in record expressions to spread fields from another record:
let updated = { ...base, name: "bob" }Assignment (=)
Section titled “Assignment (=)”var x = 1x = x + 1 // reassign (var only)m["key"] = value // map index write (var only)xs[i] = value // list index write (var only)Arrows (-> =>)
Section titled “Arrows (-> =>)”->separates parameter types from return type in function signatures=>separates patterns/parameters from bodies in match arms and lambdas
fn add(a: Int, b: Int) -> Int = a + b(x) => x + 1match color { Red => "red", Blue => "blue" }Bitwise Operations
Section titled “Bitwise Operations”Bitwise operations are provided as stdlib functions, not operators:
int.band(a, b) // bitwise ANDint.bor(a, b) // bitwise ORint.bxor(a, b) // bitwise XORint.bnot(a) // bitwise NOTint.bshl(a, n) // shift leftint.bshr(a, n) // shift right