Operators
Arithmetic
Section titled “Arithmetic”2 + 3 // 510 - 4 // 63 * 7 // 2115 / 4 // 3.7517 % 5 // 2[1,2] + [3,4] // [1, 2, 3, 4] (array concat)Comparison
Section titled “Comparison”3 < 5 // true3 > 5 // false3 <= 3 // true3 >= 5 // falseEquality
Section titled “Equality”Works on any types. Arrays and maps compare by value.
1 == 1 // true"hi" == "hi" // true[1, 2] == [1, 2] // truenil == nil // true1 == "1" // falseFloating-point note: == uses exact equality. Due to IEEE 754, 0.1 + 0.2 != 0.3. Use math.approx() for approximate comparison:
0.1 + 0.2 == 0.3 // falsemath.approx(0.1 + 0.2, 0.3) // trueLogical
Section titled “Logical”&& and || short-circuit and return the deciding value, not just true/false.
true && "yes" // "yes"false && "yes" // falsenil || "default" // "default"true || "other" // true!true // false!nil // trueTernary
Section titled “Ternary”let label = x > 5 ? "big" : "small"let grade = score >= 90 ? "A" : score >= 80 ? "B" : "C"Optional chaining
Section titled “Optional chaining”?. accesses a property only if the object is non-nil. Returns nil if the object is nil or the field does not exist.
let user = {address: {city: "Lisbon"}}print(user?.address?.city) // "Lisbon"print(user?.phone?.number) // nil (no error)
let x = nilprint(x?.name) // nil?[ does the same for index access:
let arr = nilprint(arr?[0]) // nilNil coalescing
Section titled “Nil coalescing”?? returns the left side if non-nil, otherwise evaluates the right side (short-circuit).
let name = nil ?? "anonymous" // "anonymous"let port = config?.port ?? 8080 // 8080 if port is nillet x = 0 ?? 42 // 0 (not nil, so left wins)Chains naturally with ?.:
let city = user?.address?.city ?? "unknown"Compound assignment
Section titled “Compound assignment”let x = 10x += 5 // 15x -= 3 // 12x *= 2 // 24x /= 4 // 6x %= 4 // 2Increment / Decrement
Section titled “Increment / Decrement”let i = 0i++ // i is now 1i-- // i is now 0Pipe operator
Section titled “Pipe operator”The pipe operator |> passes the left side as the first argument to the right side:
// Without pipeprint(sort(filter(nums, lam{ n in n > 5 })))
// With pipenums |> filter(lam{ n in n > 5 }) |> sort |> printa |> f becomes f(a). a |> f(x) becomes f(a, x).
See Functions for more pipe examples.
Bitwise operators
Section titled “Bitwise operators”| Operator | Description |
|---|---|
& | Bitwise AND |
| | Bitwise OR |
^ | Bitwise XOR |
~ | Bitwise NOT (unary) |
<< | Left shift |
>> | Right shift |
255 & 15 // 15240 | 15 // 255255 ^ 15 // 240~0 // -11 << 8 // 256256 >> 4 // 16All values are converted to 64-bit integers for bitwise operations. Note: | is bitwise OR, |> is the pipe operator, || is logical OR.
Type checking (is)
Section titled “Type checking (is)”42 is "int" // true"hello" is "string" // true
class Dog extends Animal {}let d = Dog()d is Dog // trued is Animal // trueSee Data Types for supported type names.
Operator precedence
Section titled “Operator precedence”From highest to lowest:
| Precedence | Operators | Description |
|---|---|---|
| 1 | () [] . | Call, index, field access |
| 2 | ++ -- | Postfix increment/decrement |
| 3 | - ! ~ | Unary negation, logical NOT, bitwise NOT |
| 4 | * / % | Multiplication, division, modulo |
| 5 | + - | Addition, subtraction |
| 6 | << >> | Bitwise shift |
| 7 | & | Bitwise AND |
| 8 | ^ | Bitwise XOR |
| 9 | | | Bitwise OR |
| 10 | < > <= >= | Comparison |
| 11 | == != | Equality |
| 12 | && | Logical AND |
| 13 | || | Logical OR |
| 14 | = | Assignment (right-associative) |
Parentheses can override precedence:
print(2 + 3 * 4) // 14print((2 + 3) * 4) // 20