`switch` Expression
===================

{{#include ../links.md}}

The `switch` _expression_ allows matching on literal values, and it mostly follows Rust's
`match` syntax:

```c
switch calc_secret_value(x) {
    1 => print("It's one!"),
    2 => {
        print("It's two!");
        print("Again!");
    }
    3 => print("Go!"),
    // _ is the default when no cases match
    _ => print("Oops! Something's wrong: " + x)
}
```


Expression, Not Statement
------------------------

`switch` is not a statement, but an expression. This means that a `switch` expression can
appear anywhere a regular expression can, e.g. as function call arguments.

```c
let x = switch foo { 1 => true, _ => false };

func(switch foo {
    "hello" => 42,
    "world" => 123,
    _ => 0
});

// The above is somewhat equivalent to:

let x = if foo == 1 { true } else { false };

if foo == "hello" {
    func(42);
} else if foo == "world" {
    func(123);
} else {
    func(0);
}
```


Array and Object Map Literals Also Work
--------------------------------------

The `switch` expression can match against any _literal_, including [array] and [object map] literals.

```c
// Match on arrays
switch [foo, bar, baz] {
    ["hello", 42, true] => { ... }
    ["hello", 123, false] => { ... }
    ["world", 1, true] => { ... }
    _ => { ... }
}

// Match on object maps
switch map {
    #{ a: 1, b: 2, c: true } => { ... }
    #{ a: 42, d: "hello" } => { ... }
    _ => { ... }
}
```

Switching on [arrays] is very useful when working with Rust enums (see [this chapter]({{rootUrl}}/patterns/enums.md)
for more details).


Difference From `if` - `else if` Chain
-------------------------------------

Although a `switch` expression looks _almost_ the same as an `if`-`else if` chain,
there are subtle differences between the two.

### Look-up Table vs `x == y`

A `switch` expression matches through _hashing_ via a look-up table.
Therefore, matching is very fast.  Walking down an `if`-`else if` chain
is _much_ slower.

On the other hand, operators can be [overloaded][operator overloading] in Rhai,
meaning that it is possible to override the `==` operator for integers such
that `x == y` returns a different result from the built-in default.

`switch` expressions do _not_ use the `==` operator for comparison;
instead, they _hash_ the data values and jump directly to the correct
statements via a pre-compiled look-up table.  This makes matching extremely
efficient, but it also means that [overloading][operator overloading]
the `==` operator will have no effect.

Therefore, in environments where it is desirable to [overload][operator overloading]
the `==` operator - though it is difficult to think of valid scenarios where you'd want
`1 == 1` to return something other than `true` - avoid using the `switch` expression.

### Efficiency

Because the `switch` expression works through a look-up table, it is very efficient
even for _large_ number of cases; in fact, switching is an O(1) operation regardless
of the size of the data and number of cases to match.

A long `if`-`else if` chain becomes increasingly slower with each additional case
because essentially an O(n) _linear scan_ is performed.