Topaz provides various operators to manipulate and calculate data. Understanding the exact behavior and precedence of all operators is crucial. ⚡
🔢 Arithmetic Operators
Basic Arithmetic Operations
// Basic arithmetic operators
let a = 10
let b = 3
let addition = a + b // 13
let subtraction = a - b // 7
let multiplication = a * b // 30
let division = a / b // 3.333...
let remainder = a % b // 1
let exponentiation = a ** b // 1000
print("Addition: {addition}")
print("Subtraction: {subtraction}")
print("Multiplication: {multiplication}")
print("Division: {division}")
print("Remainder: {remainder}")
print("Exponentiation: {exponentiation}")
Unary Operators
let positive = +42 // 42 (explicit positive)
let negative = -42 // -42 (negation)
let number = 15
let negated = -number // -15
print("Original value: {number}")
print("Negated: {negated}")
Increment/Decrement
Topaz v4 does not support ++/--. Use explicit reassignment with let mut.
let mut counter = 5
counter = counter + 1
counter = counter - 1
Compound Assignment Operators
let mut value = 10
value += 5 // value = value + 5 = 15
value -= 3 // value = value - 3 = 12
value *= 2 // value = value * 2 = 24
value /= 4 // value = value / 4 = 6
value %= 4 // value = value % 4 = 2
value **= 3 // value = value ** 3 = 8
print("Final value: {value}")
🔍 Comparison Operators
Basic Comparisons
let x = 10
let y = 20
let z = 10
// Equality comparison
let equal = x == z // true
let notEqual = x != y // true
// Size comparison
let lessThan = x < y // true
let lessThanOrEqual = x <= z // true
let greaterThan = y > x // true
let greaterThanOrEqual = z >= x // true
print("x == z: {equal}")
print("x != y: {notEqual}")
print("x < y: {lessThan}")
print("y > x: {greaterThan}")
Type-Safe Comparison
// Topaz enforces type-safe comparison
let integer = 42
let float = 42.0
let string = "42"
// Only same types can be compared
let intComparison = integer == 42 // true
let floatComparison = float == 42.0 // true
// Different type comparison requires explicit conversion
let stringComparison = integer.toString() == string // true
let numberComparison = integer == parseInt(string) // true
print("Type conversion comparison: {stringComparison}")
Special Comparison Operators
Topaz v4 does not include a spaceship (<=>) operator.
🧠 Logical Operators
Basic Logical Operations
let trueValue = true
let falseValue = false
// Logical AND
let andResult = trueValue && falseValue // false
let andResult2 = trueValue && trueValue // true
// Logical OR
let orResult = trueValue || falseValue // true
let orResult2 = falseValue || falseValue // false
// Logical NOT
let notResult = !trueValue // false
let notResult2 = !falseValue // true
print("AND result: {andResult}")
print("OR result: {orResult}")
print("NOT result: {notResult}")
Short-circuit Evaluation
function sideEffectFunction() -> bool {
print("Function was called!")
return true
}
// AND short-circuit - second not executed if first is false
let shortAnd = false && sideEffectFunction() // Function not called
// OR short-circuit - second not executed if first is true
let shortOr = true || sideEffectFunction() // Function not called
print("Short AND: {shortAnd}")
print("Short OR: {shortOr}")
Null Coalescing Operator
// Null coalescing operator (??)
let value1: Option<string> = None
let value2: Option<string> = Some("default")
let value3 = "fallback"
let result1 = value1 ?? "none" // "none"
let result2 = value2 ?? "none" // "default"
let result3 = value1 ?? value2 ?? value3 // "default"
print("Null coalescing result: {result1}")
// With Option values
let user = { name: "TopazDev", age: Some(25) }
let age = match user.age { case Some(v) => v; case None => 0 }
print("Age: {age}")
Null‑Coalescing Assignment (??=)
Statement‑only assignment that initializes a variable if it is currently None/null. It does not produce an expression value and is right‑associative.
let mut name: Option<string> = None
name ??= Some("guest") // name becomes Some("guest")
name ??= Some("override") // no-op (already Some)
// Right-associative
a ??= b ??= Some(1) // same as: a ??= (b ??= Some(1))
🔧 Bitwise / Shift Operators
Not part of Topaz v4. Note that >> is reserved for function composition (see below), not bit shifting.
🎯 Special Operators
Type Operators
typeof/instanceof are not Topaz v4 operators. Use pattern matching or library introspection utilities.
Range Operators
// Range operators (.. inclusive, ..< exclusive upper bound)
let inclusive = 1..5 // 1, 2, 3, 4, 5
let exclusive = 1..<5 // 1, 2, 3, 4
for i in inclusive { print(i) }
for i in exclusive { print(i) }
Membership Operator (in)
// Arrays/Lists/Sets
let ok1 = 3 in [1, 2, 3] // true
let ok2 = "a" in Set.of("a", "b") // true
// Map keys (via keys view)
let hasId = "id" in userMap.keys // bool
// Ranges
let inside = 5 in 1..10 // true
let outside = 10 in 1..<10 // false
Spread Operator
Not part of Topaz v4 syntax.
Optional Chaining (?.)
Option-safe only. Parses when the left-hand side is Option<T> or a nullable union (e.g., T | null). This is not generic object chaining; use . for regular members.
let user: Option<{ name: string, profile: Option<{ city: string }> }> =
Some({ name: "Ann", profile: Some({ city: "Seoul" }) })
let nameOpt = user?.name // Option<string>
let cityOpt = user?.profile?.city // Option<string>
let city = user?.profile?.city ?? "Unknown" // string
let noneUser: Option<{ name: string }> = None
let fallback = noneUser?.name ?? "guest" // "guest"
// Desugars to Option.map/flatMap chains
// user?.profile?.city ≃ user |> Option.flatMap(_, u => u.profile) |> Option.map(_, p => p.city)
Pipe Operator
// Pipe operator (|>)
let result = 10
|> (x => x * 2) // 20
|> (x => x + 5) // 25
|> (x => x.toString()) // "25"
// Useful for function chaining
let data = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
|> (arr => arr.filter(x => x % 2 == 0)) // [2, 4, 6, 8, 10]
|> (arr => arr.map(x => x * x)) // [4, 16, 36, 64, 100]
|> (arr => arr.reduce((a, b) => a + b)) // 220
print("Pipe result: {result}")
print("Chaining result: {data}")
⚡ Operator Precedence (Topaz v4)
v4// High → Low; associativity in parentheses
1) Calls/Index/Member: () [] . ?. (left)
2) Exponentiation: ** (right)
3) Unary: + - ! (right)
4) Multiplicative: * / % (left)
5) Additive: + - (left)
6) Range: .. ..< (left) // lower than arithmetic, higher than comparison
7) Comparison: < <= > >= == != in (left)
8) Logical AND: && (left)
9) Logical OR: || (left)
10) Null coalescing: ?? (left)
11) Function composition: >> (right)
12) Pipeline: |> (left)
13) Assignment: = …, ??= (right)
// Composition vs Pipeline precedence
// |> has lower precedence than >>
let h = f >> g
let x = input |> h // equals: input |> (f >> g)
// Range precedence
let within = 3 >= (1..5).min() && 3 <= (1..5).max()
Function Composition (>>)
// Point-free style
let normalize = trim >> toLowerCase >> collapseSpaces
print(normalize(" Hello WORLD ")) // "hello world"
🔄 Operator Overloading
Custom Type Operators
// Implementing operators for structs
struct Vector {
x: float,
y: float
}
impl Vector {
// Overload + operator
function +(other: Vector) -> Vector {
return Vector { x: self.x + other.x, y: self.y + other.y }
}
// Overload * operator (scalar multiplication)
function *(scalar: float) -> Vector {
return Vector { x: self.x * scalar, y: self.y * scalar }
}
// Overload == operator
function ==(other: Vector) -> bool {
return self.x == other.x && self.y == other.y
}
// String conversion
function toString() -> string {
return "Vector({self.x}, {self.y})"
}
}
// Usage examples
let vector1 = Vector { x: 3.0, y: 4.0 }
let vector2 = Vector { x: 1.0, y: 2.0 }
let sum = vector1 + vector2 // Vector(4.0, 6.0)
let scaled = vector1 * 2.0 // Vector(6.0, 8.0)
let equal = vector1 == vector2 // false
print("Vector sum: {sum}")
print("Vector scaled: {scaled}")
print("Vectors equal: {equal}")
🛡️ Safe Operator Usage
1. Overflow Handling
// Checked arithmetic operations
let largeNum1 = 2147483647 // max int value
let largeNum2 = 1
// Safe addition (overflow check)
match largeNum1.checkedAdd(largeNum2) {
case Some(result) => print("Safe addition: {result}")
case None => print("Overflow occurred!")
}
// Saturating operations (clamp to max/min values)
let saturatingAdd = largeNum1.saturatingAdd(largeNum2) // stays at max int
print("Saturating addition: {saturatingAdd}")
2. Division by Zero Prevention
function safeDivide(numerator: float, denominator: float) -> Result<float, string> {
if denominator == 0.0 {
return Err("Cannot divide by zero")
}
return Ok(numerator / denominator)
}
// Usage example
match safeDivide(10.0, 0.0) {
case Ok(result) => print("Division result: {result}")
case Err(error) => print("Error: {error}")
}
3. Type Safety
// Ensure safety with explicit type conversion
let stringNumber = "123"
let actualNumber = match parseInt(stringNumber) {
case Ok(number) => number
case Err(_) => {
print("Number conversion failed")
0 // default value
}
}
let result = actualNumber + 100
print("Safe calculation result: {result}")
📊 Performance Optimization Tips
1. Expensive Operation Optimization
// Use multiplication instead of exponentiation (for small exponents)
let square = value * value // instead of value ** 2
let cube = value * value * value // instead of value ** 3
// Use multiplication instead of division
let half = value * 0.5 // instead of value / 2
// Optimize modulo operations (powers of 2)
let remainder = value & 7 // instead of value % 8 (8 = 2^3)
2. Leverage Short-circuit Evaluation
// Put expensive function calls later
let result = simpleCondition() && expensiveFunction()
// Optimize null checks with Option helpers
let value = object?.property?.subProperty ?? defaultValue
Understanding and properly using Topaz operators allows you to write efficient and safe code! Always keep operator precedence and type safety in mind. 🎯