Conditionals
How different programming languages express branching logic.
JavaScript
if/else and switch (with loose comparison and fallthrough by default)
cover branching, alongside the ternary operator. switch only does simple
equality checks, so there’s no structural pattern matching built in.
Python
if/elif/else and a conditional expression (x if cond else y) handle
most branching. Python 3.10 added match/case for structural pattern
matching against literals, types, and destructured sequences/mappings.
TypeScript
Same runtime conditionals as JavaScript, but the compiler performs control
flow analysis to narrow union types across if/switch branches, making
discriminated-union switches a common and type-safe pattern.
Java
if/else and ternary as usual. switch supports classic fallthrough
statements as well as modern switch expressions with arrow syntax, and newer
versions add pattern matching for switch over types and record shapes.
C#
if/else and ternary as usual. switch supports both traditional
statements and expressive switch expressions with type patterns, relational
patterns, and property patterns for rich structural matching.
C++
Inherits C’s conditionals and adds if constexpr for compile-time
branching during template instantiation, plus structured bindings that can
be introduced directly within an if or switch initializer.
C
if/else, switch with fallthrough requiring explicit break, and the
ternary operator. No structural pattern matching is available.
PHP
if/elseif/else and switch (loose comparison, with fallthrough) cover
traditional branching. The match expression (PHP 8+) offers strict
comparison and no fallthrough, plus the ternary and null-coalescing
operators for compact checks.
Go
if/else supports an optional init statement scoped to the branch.
switch doesn’t fall through by default (needs explicit fallthrough), and
a type switch lets code branch on an interface’s dynamic type. No ternary
operator exists.
Rust
if is an expression that can produce a value. match provides exhaustive
pattern matching with guards and destructuring, and if let/while let
offer concise matching against a single pattern, commonly Option/Result.
Kotlin
if is an expression, making the ternary operator unnecessary. when
replaces switch with much more power — matching ranges, types, multiple
values, or arbitrary conditions in a single construct.
Ruby
if/elsif/else, the negated unless, and postfix modifiers (do_thing if condition) for concise one-liners. case/when uses the flexible ===
operator, enabling matches against classes, ranges, and regexes.
Dart
if/else and the ternary (?:) operator handle simple branching, with
null-aware operators (??, ?.) filling in for null checks. Since Dart 3,
switch supports rich pattern matching over types, records, and destructured
values, including when guard clauses.
Swift
if/else and guard (for early-exit validation) handle simple branching.
switch must be exhaustive and supports rich pattern matching over ranges,
tuples, and where clauses, with no implicit fallthrough between cases.
Perl
if/unless/elsif/else cover branching, with postfix conditionals
(do_thing if $condition) for concise one-liners and a standard ternary
operator. Perl has no traditional switch statement; the experimental
given/when construct exists but is deprecated in favor of chained if.
Elixir
cond evaluates a list of boolean expressions in order, while case
pattern-matches a value against clauses with optional guards. if/unless
exist as convenience macros for simple binary branches; there is no
traditional switch.
Scala
if/else is an expression that returns a value, so a separate ternary
operator isn’t needed. match provides powerful pattern matching over case
classes, types, sequences, and guards, commonly replacing both switch and
long conditional chains.
Clojure
Being a Lisp, branching is expression-based via if, if-let, when,
cond, and case, each returning a value rather than executing a
statement. There’s no traditional switch; cond handles multi-branch
logic and case does fast dispatch on constant values.
Haskell
if/then/else is an expression requiring both branches to produce the
same type, with no bare else-less form. Guards on function equations and
case expressions with pattern matching are the idiomatic way to branch,
and there’s no traditional switch or ternary operator.