Operators
Charl provides a comprehensive set of operators for arithmetic, comparison, and logical operations.
Operator Overview
| Category | Operators | Description |
|---|---|---|
| Arithmetic | + - * / % | Basic mathematical operations |
| Comparison | == != < <= > >= | Compare values, return bool |
| Logical | && || ! | Boolean logic operations |
Arithmetic Operators
Arithmetic operators perform mathematical calculations on numeric types (int and float).
Addition (+)
// Integer addition
let sum1 = 5 + 3 // 8
let sum2 = 100 + 200 // 300
// Float addition
let sum3 = 3.14 + 2.86 // 6.0
let sum4 = 0.1 + 0.2 // 0.3
// Negative numbers
let sum5 = -5 + 10 // 5
let sum6 = -3 + -7 // -10
Note: Cannot mix int and float directly. Use explicit conversion: float(int_val) + float_val
Subtraction (-)
// Integer subtraction
let diff1 = 10 - 3 // 7
let diff2 = 5 - 8 // -3
// Float subtraction
let diff3 = 9.5 - 4.2 // 5.3
let diff4 = 1.0 - 0.1 // 0.9
Multiplication (*)
// Integer multiplication
let prod1 = 5 * 3 // 15
let prod2 = -4 * 7 // -28
// Float multiplication
let prod3 = 2.5 * 4.0 // 10.0
let prod4 = 3.14 * 2.0 // 6.28
// Mixed signs
let prod5 = -5 * -3 // 15
let prod6 = -2.0 * 5.0 // -10.0
Division (/)
// Integer division (truncates toward zero)
let quot1 = 10 / 3 // 3
let quot2 = 15 / 4 // 3
let quot3 = -10 / 3 // -3
// Float division
let quot4 = 10.0 / 3.0 // 3.333...
let quot5 = 7.5 / 2.5 // 3.0
let quot6 = 1.0 / 3.0 // 0.333...
Warning: Division by zero will cause a runtime error for integers, or produce infinity for floats.
Modulo (%)
Returns the remainder after division. Only works with integers.
// Modulo operation
let rem1 = 10 % 3 // 1
let rem2 = 15 % 4 // 3
let rem3 = 20 % 5 // 0
// Negative numbers
let rem4 = -10 % 3 // -1
let rem5 = 10 % -3 // 1
// Common use: check if even/odd
let is_even = (x % 2) == 0
let is_odd = (x % 2) != 0
Comparison Operators
Comparison operators compare two values and return a boolean result (true or false).
| Operator | Name | Example | Result |
|---|---|---|---|
| == | Equal to | 5 == 5 | true |
| != | Not equal to | 5 != 3 | true |
| < | Less than | 3 < 5 | true |
| <= | Less than or equal | 5 <= 5 | true |
| > | Greater than | 7 > 5 | true |
| >= | Greater than or equal | 5 >= 5 | true |
Examples
// Equality comparisons
let equal1 = 5 == 5 // true
let equal2 = 5 == 3 // false
let not_eq = 5 != 3 // true
// Numeric comparisons
let less = 3 < 5 // true
let less_eq = 5 <= 5 // true
let greater = 7 > 5 // true
let greater_eq = 5 >= 5 // true
// With floats
let float_eq = 3.14 == 3.14 // true
let float_lt = 2.5 < 3.5 // true
// Boolean comparisons
let bool_eq = true == true // true
let bool_ne = true != false // true
// String comparisons (lexicographic)
let str_eq = "hello" == "hello" // true
let str_ne = "hello" != "world" // true
let str_lt = "apple" < "banana" // true
Note: Float equality should be used carefully due to precision issues. Consider using a tolerance for approximate equality checks.
Logical Operators
Logical operators combine or modify boolean values.
AND Operator (&&)
Returns true only if both operands are true.
// Basic AND
let and1 = true && true // true
let and2 = true && false // false
let and3 = false && true // false
let and4 = false && false // false
// Combining conditions
let age = 25
let has_license = true
let can_drive = age >= 18 && has_license // true
// Multiple conditions
let x = 10
let valid = x > 0 && x < 100 && x % 2 == 0 // true
Short-circuit evaluation: If the left operand is false, the right operand is not evaluated.
OR Operator (||)
Returns true if at least one operand is true.
// Basic OR
let or1 = true || true // true
let or2 = true || false // true
let or3 = false || true // true
let or4 = false || false // false
// Combining conditions
let is_weekend = day == "Saturday" || day == "Sunday"
// Multiple conditions
let can_proceed = has_permission || is_admin || is_owner
Short-circuit evaluation: If the left operand is true, the right operand is not evaluated.
NOT Operator (!)
Negates a boolean value.
// Basic NOT
let not1 = !true // false
let not2 = !false // true
// Negating conditions
let is_valid = x > 0
let is_invalid = !is_valid
// Double negation
let original = true
let double_not = !!original // true (same as original)
// With comparisons
let not_equal = !(x == y) // Same as x != y
let not_less = !(x < y) // Same as x >= y
Truth Tables
AND (&&)
| A | B | A && B |
|---|---|---|
| true | true | true |
| true | false | false |
| false | true | false |
| false | false | false |
OR (||)
| A | B | A || B |
|---|---|---|
| true | true | true |
| true | false | true |
| false | true | true |
| false | false | false |
Operator Precedence
When multiple operators appear in an expression, they are evaluated according to their precedence (priority).
| Precedence | Operators | Description |
|---|---|---|
| Highest | ! | Logical NOT |
| ↓ | * / % | Multiplication, Division, Modulo |
| ↓ | + - | Addition, Subtraction |
| ↓ | < <= > >= | Comparison operators |
| ↓ | == != | Equality operators |
| ↓ | && | Logical AND |
| Lowest | || | Logical OR |
Precedence Examples
// Multiplication before addition
let result1 = 2 + 3 * 4 // 14, not 20
// Equivalent to: 2 + (3 * 4)
// Division before subtraction
let result2 = 10 - 6 / 2 // 7, not 2
// Equivalent to: 10 - (6 / 2)
// Comparison before logical AND
let result3 = x > 0 && y < 10
// Equivalent to: (x > 0) && (y < 10)
// AND before OR
let result4 = true || false && false // true
// Equivalent to: true || (false && false)
// Use parentheses for clarity
let result5 = (2 + 3) * 4 // 20
let result6 = (10 - 6) / 2 // 2
let result7 = (true || false) && false // false
Best Practice: Use parentheses to make complex expressions clear, even when not strictly necessary.
Complex Examples
Example 1: Range Checking
// Check if value is in range [min, max]
let value = 50
let min = 0
let max = 100
let in_range = value >= min && value <= max // true
// Check if value is outside range
let out_of_range = value < min || value > max // false
Example 2: Validation Logic
// Complex validation
let age = 25
let has_id = true
let has_permission = false
let is_admin = false
// Can enter if: (adult with ID) OR (has permission) OR (is admin)
let can_enter = (age >= 18 && has_id) || has_permission || is_admin
// Must meet all criteria
let fully_verified = age >= 21 && has_id && has_permission
Example 3: Mathematical Formulas
// Quadratic formula: (-b ± sqrt(b²-4ac)) / 2a
let a = 1.0
let b = -5.0
let c = 6.0
// Discriminant
let discriminant = b * b - 4.0 * a * c
// Check if real solutions exist
let has_real_solutions = discriminant >= 0.0
// Distance formula: sqrt((x2-x1)² + (y2-y1)²)
let x1 = 0.0
let y1 = 0.0
let x2 = 3.0
let y2 = 4.0
let dx = x2 - x1
let dy = y2 - y1
let distance_squared = dx * dx + dy * dy // 25.0
Example 4: ML Conditions
// Training loop conditions
let epoch = 50
let max_epochs = 100
let loss = 0.001
let min_loss = 0.0001
let patience_counter = 5
let max_patience = 10
// Continue training if not converged and not timed out
let should_continue = epoch < max_epochs &&
loss > min_loss &&
patience_counter < max_patience
// Check for improvement
let epsilon = 0.0001
let prev_loss = 0.0015
let improved = (prev_loss - loss) > epsilon
Best Practices
DO:
- Use parentheses to clarify complex expressions
- Space operators for readability:
x + ynotx+y - Break very long expressions into multiple lines
- Use comparison operators consistently (e.g., always
x == y, not mixing withy == x) - Consider using intermediate variables for complex calculations
DON'T:
- Rely on precedence rules for complex expressions without parentheses
- Use float equality without considering precision: prefer tolerance checks
- Mix types without explicit conversion
- Chain many operations without intermediate variables
- Overuse negation operators - prefer positive conditions when possible