Everyone must be using selection statements for pattern matching or equality checking. Some language like Rust
, F#
, Kotlin
, Scala
, V
and Python
(future) use match
and while some use switch
like C
, C++
, Go
, C#
etc.
What was the need for separate names for the same purpose? This article tries to clarify the difference and usage between these two.
switch
statement
A switch
statement allows a variable to be tested for equality against a list of values. Each value is called case
but needs to be terminated by break
. switch
can also have a default
case for handling other cases which are not listed.
Here's a simple switch
Statement Program in C++.
#include <iostream>
int main()
{
int i = 0;
switch (i)
{
case 0:
std::cout << "i is zero";
break;
case 1:
std::cout << "i is one";
break;
default:
std::cout << "invalid";
break;
}
}
This program declares variable i
as int
and the switch
statement checks the value of i
. The first case will be evaluated as it satisfied the condition i == 0
so i is zero
will be printed.
Though switch
has certain limitations:
-
switch
only works with integral values i.e.int
,char
andenum
-
switch
can only be used for checking equality -
switch
cannot be used as an expression
match
statement/expression
match
can be used both used as a statement and expression accordingly and are much like switch
except it solves the above limitation stated plus saves additional keywords over switch like no default
or case
(though Python has case
and it's a statement). default
is either replaced with else
or _
(some may just use default).
match
also supports range like 1..2
which means in a range of [1, 2)
and 1..=3
or 1...3
which means [1, 3]
, 2 | 3 | 4
or 3, 4, 5
for matching if either of them is true plus matching them as a var
/object
.
The following examples of match
are written in Rust.
Taken from Learn Rust by Examples
Simple example
fn main() {
let x = 1;
match x {
1 => println!("one"),
2 => println!("two"),
3 => println!("three"),
4 => println!("four"),
5 => println!("five"),
// else clause, executed when none of the values matches
_ => println!("something else"),
}
}
Using ranges and combining multiple values as an expression
fn main() {
let x = 1;
let message = match x {
0 | 1 => "not many", // check if matches either to 0 or 1
2..=9 => "a few", // check if its in a range of `[2, 9]`
10..15 => "too many", // check if its in a range of `[10, 15)`
// else clause, if neither of the cases matches then "lots of
// many" will be assigned
_ => "lots of many",
};
assert_eq!(message, "a few");
}
Exceptions
Some languages like Go
, JS
, TS
etc have switch statements but support all primitive data types though they don't have support for ranges, using them as expressions and have default
as the keyword, pattern matching etc.
In Go, there's no need to put break
on every case, it does it automatically plus you can use interface{}
to detect the type of the variable.
An example of Go's switch
Taken from Go By Examples
Simple example
package main
import (
"fmt"
"time"
)
func main() {
// Here's a basic `switch`.
i := 2
fmt.Print("Write ", i, " as ")
switch i {
case 1:
fmt.Println("one")
case 2:
fmt.Println("two")
case 3:
fmt.Println("three")
}
// You can use commas to separate multiple expressions
// in the same `case` statement. We use the optional
// `default` case in this example as well.
switch time.Now().Weekday() {
case time.Saturday, time.Sunday:
fmt.Println("It's the weekend")
default:
fmt.Println("It's a weekday")
}
// `switch` without an expression is an alternate way
// to express if/else logic. Here we also show how the
// `case` expressions can be non-constants.
t := time.Now()
switch {
case t.Hour() < 12:
fmt.Println("It's before noon")
default:
fmt.Println("It's after noon")
}
// A type `switch` compares types instead of values. You
// can use this to discover the type of an interface
// value. In this example, the variable `t` will have the
// type corresponding to its clause.
whatAmI := func(i interface{}) {
switch t := i.(type) {
case bool:
fmt.Println("I'm a bool")
case int:
fmt.Println("I'm an int")
default:
fmt.Printf("Don't know type %T\n", t)
}
}
whatAmI(true)
whatAmI(1)
whatAmI("hey")
}
Conclusions
match
and switch
are just convenient ways of writing long if-else
statements for increasing readability and making code more robust etc.
Usually, match
is used for pattern matching and also it can be a statement and as well as expression whereas switch
is used for equality checking and is a statement only.
Some languages might not even use switch
(f.e. Kotlin with the when
which has the same semantics as match
)
Dynamically and statically typed languages often do things differently on their specific use cases. Some may provide or disallow certain features so that the language doesn't become much complex.
Similarly, V only supports the inclusive range of the last element i.e. start...end
which is the same as [start, end]
to remove the complexity.
Some languages may even keep switch
for simplicity and easiness to use.
References
- Match in Rust
- Match in V
- Match in Python
- Match in F#
- Match in Scala
- Switch in Go
- Match in Kotlin
- Switch in C#
- Pattern Matching
If there's anything wrong in this article then please reply in the comments.
Top comments (0)