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:

OperatorDescriptionExample
+Addition3 + 2 = 5
-Subtraction3 - 2 = 1
*Multiplication3 * 2 = 6
/Division7 / 2 = 3
%Modulo7 % 2 = 1
**Exponentiation2 ** 10 = 1024

The + operator also concatenates strings:

"hello" + " " + "world"   // "hello world"

Comparison

Comparison operators return a boolean value:

OperatorDescription
==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:

OperatorDescriptionExample
&&Logical ANDtrue && false = false
||Logical ORtrue || 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]        // true

For 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?.city

If 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:

OperatorDescriptionExample
&Bitwise AND0xFF & 0x0F = 15
|Bitwise OR0xF0 | 0x0F = 255
^Bitwise XOR0xFF ^ 0x0F = 240
<<Left shift1 << 4 = 16
>>Right shift256 >> 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 5

Compound Assignment

Compound assignment operators combine an arithmetic operation with assignment:

OperatorDescription
+=Add and assign
-=Subtract and assign
*=Multiply and assign
/=Divide and assign
let x = 10
x += 5    // 15
x -= 3    // 12
x *= 2    // 24

Risor © 2026 Deep Noodle