Operators
Risor supports a familiar set of operators for arithmetic, comparison, logic, membership testing, piping, spreading, and optional chaining.
Arithmetic
Standard arithmetic operators work on integers and floats:
| Operator | Description | Example |
|---|---|---|
+ | Addition | 3 + 2 = 5 |
- | Subtraction | 3 - 2 = 1 |
* | Multiplication | 3 * 2 = 6 |
/ | Division | 7 / 2 = 3 |
% | Modulo | 7 % 2 = 1 |
** | Exponentiation | 2 ** 10 = 1024 |
The + operator also concatenates strings:
"hello" + " " + "world" // "hello world"Comparison
Comparison operators return a boolean value:
| Operator | Description |
|---|---|
== | Equal |
!= | Not equal |
< | Less than |
> | Greater than |
<= | Less than or equal |
>= | Greater than or equal |
Logical
Logical operators work with boolean values and follow short-circuit evaluation:
| Operator | Description | Example |
|---|---|---|
&& | Logical AND | true && false = false |
|| | Logical OR | true || false = true |
! | Logical NOT | !true = false |
Membership
The in and not in operators test whether a value is present in a
collection:
"x" in {x: 1} // true
"z" in {x: 1} // false
3 in [1, 2, 3] // true
3 not in [1, 2] // trueFor maps, in checks for the presence of a key. For lists, it checks for
the presence of a value.
Pipe Operator
The pipe operator |> passes the result of the left-hand expression as
the argument to the right-hand expression:
let double = x => x * 2
5 |> double // 10
[3, 1, 2] |> sorted |> reversed // [3, 2, 1]Pipes create a readable left-to-right data flow and are especially useful for chaining transformations on collections.
Spread Operator
The spread operator ... expands a list or map into its individual elements.
Spread a list into another list:
let a = [1, 2]
let b = [...a, 3, 4] // [1, 2, 3, 4]Merge maps:
let merged = {...{a: 1}, ...{b: 2}} // {a: 1, b: 2}Spread arguments into a function call:
let args = [1, 2, 3]
fn(...args)Optional Chaining
The ?. operator safely accesses properties and methods on values that may
be nil. If the left-hand side is nil, the entire expression evaluates
to nil instead of raising an error:
obj?.field?.nested
obj?.method()This is useful when working with data structures that may have missing or optional fields:
let city = user?.address?.cityIf user is nil or user.address is nil, the result is nil rather
than an error.
Nullish Coalescing
The ?? operator returns the right-hand operand when the left-hand operand
is nil:
let name = nil
name ?? "anonymous" // "anonymous"
let x = 0
x ?? 42 // 0 (only nil triggers the fallback)Bitwise Operators
Risor supports standard bitwise operations on integers:
| Operator | Description | Example |
|---|---|---|
& | Bitwise AND | 0xFF & 0x0F = 15 |
| | Bitwise OR | 0xF0 | 0x0F = 255 |
^ | Bitwise XOR | 0xFF ^ 0x0F = 240 |
<< | Left shift | 1 << 4 = 16 |
>> | Right shift | 256 >> 4 = 16 |
Increment and Decrement
The postfix ++ and -- operators increment or decrement a variable by one:
let x = 5
x++ // x is now 6
x-- // x is now 5Compound Assignment
Compound assignment operators combine an arithmetic operation with assignment:
| Operator | Description |
|---|---|
+= | Add and assign |
-= | Subtract and assign |
*= | Multiply and assign |
/= | Divide and assign |
let x = 10
x += 5 // 15
x -= 3 // 12
x *= 2 // 24