Skip to main content

Operators

Operators are symbols that perform operations on values. Here's how different languages handle arithmetic, comparison, logical, and bitwise operators.

Arithmetic & Assignment Operators​

// Arithmetic
5 + 3; // 8 (addition)
5 - 3; // 2 (subtraction)
5 * 3; // 15 (multiplication)
5 / 3; // 1.6667 (division)
5 % 3; // 2 (modulo)
5 ** 3; // 125 (exponentiation)

// Increment / Decrement
let x = 5;
x++; // 6 (post-increment)
++x; // 7 (pre-increment)
x--; // 6 (post-decrement)

// Assignment
x += 3; // x = x + 3
x -= 2; // x = x - 2
x *= 4; // x = x * 4
x /= 2; // x = x / 2
x %= 3; // x = x % 3
x **= 2; // x = x ** 2

Comparison & Logical Operators​

// Comparison
5 == "5"; // true (loose equality)
5 === "5"; // false (strict equality)
5 != "5"; // false (loose inequality)
5 !== "5"; // true (strict inequality)
5 > 3; // true
5 >= 5; // true
5 < 10; // true
5 <= 5; // true

// Logical
true && false; // false (AND)
true || false; // true (OR)
!true; // false (NOT)

// Nullish coalescing
null ?? "default"; // "default"
undefined ?? "default"; // "default"
0 ?? "default"; // 0

// Optional chaining
user?.address?.city;
arr?.[0];
func?.();

Key Takeaways​

  • Operator overloading is language-dependent -- C++ and Swift allow custom operators for user-defined types; Rust uses traits like Add and Sub for overloading. Python allows __add__, __sub__, and similar methods to define operator behavior. Go and Java forbid operator overloading for user types, so you use methods instead (e.g., a.Add(b) in Go). If you need expressive numeric or domain-specific operators (e.g., vector math), prefer C++, Rust, Swift, or Python; if you want simpler, more predictable semantics, Go or Java may be better.

  • Null coalescing (??) and optional chaining (?.) -- JavaScript, C#, Swift, PHP 8+, and Ruby support ?? for default values when a value is null/undefined and ?. for safe property access. For example, user?.address?.city ?? "unknown" avoids null pointer errors. Go and Rust have no null; Go uses explicit nil checks; Rust uses Option with unwrap_or(0) or orelse 0 in Zig. C and Java lack built-in equivalents and rely on manual checks or libraries. When working with nullable data, prefer languages with first-class null handling to reduce boilerplate and bugs.

  • Overflow behavior differs -- Zig panics on overflow in debug builds and wraps in release; Rust offers checked_add, wrapping_add, and saturating_add so you choose the behavior. C and C++ have undefined behavior on integer overflow, which can lead to security issues. JavaScript and Python use arbitrary-precision integers, so overflow is effectively absent. For safe numeric code, use Rust's checked APIs or Zig's explicit operators; avoid relying on C/C++ overflow semantics.

  • Integer division semantics -- Python 3's / always returns a float (5 / 3 is 1.666...); // is floor division for integers. C, Go, Rust, and Java use truncating division for integers (5 / 3 is 1). This affects portability when moving numeric code between languages. For consistency, use explicit floor division (// in Python, @divTrunc in Zig) or cast to float when you need fractional results. When porting algorithms, double-check division semantics to avoid off-by-one or rounding errors.

  • Increment/decrement operators are absent in some languages -- Rust, Python, Swift, and Zig omit ++ and --; Go has them but only as statements (e.g., x++), not expressions. These languages prefer explicit x += 1 for clarity and to avoid pre/post-increment confusion (e.g., i++ vs ++i). C, C++, C#, Java, JavaScript, and PHP retain ++/--. If you switch between languages, default to x += 1 where available to avoid portability issues and subtle bugs.