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
truetruetrue
truefalsefalse
falsetruefalse
falsefalsefalse

OR (||)

A B A || B
truetruetrue
truefalsetrue
falsetruetrue
falsefalsefalse

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 + y not x+y
  • Break very long expressions into multiple lines
  • Use comparison operators consistently (e.g., always x == y, not mixing with y == 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

Next Steps