Uses and difference b/w switch and match
Tags: computerscience, rust, go, cpp
Published: 2020-09-10 08:22:00

Everyone must be using selection statements for [pattern matching](https://en.wikipedia.org/wiki/Pattern_matching) or equality checking. Some language like `Rust`, `F#`, `Kotlin`, `Scala`, `V` and `Python` [(future)](https://github.com/gvanrossum/patma) 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++.

```cpp
#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` and `enum`
- `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`](https://doc.rust-lang.org/stable/rust-by-example/flow_control/match.html)*

### Simple example

```rust
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

```rust
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`](https://play.golang.org/p/qVDqWoUQ6AI)*

### Simple example

```go
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](https://en.wikipedia.org/wiki/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`](https://kotlinlang.org/docs/reference/control-flow.html#when-expression) 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](https://doc.rust-lang.org/stable/rust-by-example/flow_control/match.html)
- [Match in V](https://github.com/vlang/v/blob/master/doc/docs.md#match)
- [Match in Python](https://github.com/gvanrossum/patma)
- [Match in F#](https://docs.microsoft.com/en-us/dotnet/fsharp/language-reference/pattern-matching)
- [Match in Scala](https://www.scala-lang.org/files/archive/spec/2.11/08-pattern-matching.html)
- [Switch in Go](https://gobyexample.com/switch)
- [Match in Kotlin](https://kotlinlang.org/docs/reference/control-flow.html#when-expression)
- [Switch in C#](https://docs.microsoft.com/en-us/dotnet/csharp/pattern-matching)
- [Pattern Matching](https://en.wikipedia.org/wiki/Pattern_matching)

If there's anything wrong in this article then please reply in the comments.