|
| 1 | +# Match Expression |
| 2 | + |
| 3 | +A match expression conditionally executes code branches. |
| 4 | +Which branch is executed depends on the input to the match expression. |
| 5 | + |
| 6 | +```rust |
| 7 | +let result: u32 = match f(42) { |
| 8 | + Left(x: u32) => x, |
| 9 | + Right(x: u16) => jet::left_pad_low_16_32(x), |
| 10 | +}; |
| 11 | +``` |
| 12 | + |
| 13 | +In the above example, the output of the function call `f(42)` is matched. |
| 14 | +`f` returns an output of type `Either<u32, u16>`. |
| 15 | +If `f(42)` returns a value that matches the pattern `Left(x: u32)`, then the first match arm is executed. |
| 16 | +This arm simply returns the value `x`. |
| 17 | +Alternatively, if `f(42)` returns a value that matches the pattern `Right(x: u16)`, then the second match arm is executed. |
| 18 | +This arm extends the 16-bit number `x` to a 32-bit number by padding its left with zeroes. |
| 19 | +Because of type constraints, the output of `f` must match one of these two patterns. |
| 20 | +The whole match expression returns a value of type `u32`, from one of the two arms. |
| 21 | + |
| 22 | +## Explicit typing |
| 23 | + |
| 24 | +In Simfony, the type of variables inside match arms must **always** be written. |
| 25 | +This is different from Rust, which has better type inference. |
| 26 | + |
| 27 | +## Pattern matching |
| 28 | + |
| 29 | +There is limited support for pattern matching inside match expressions. |
| 30 | + |
| 31 | +Boolean values can be matched. |
| 32 | +The Boolean match expression is the replacement for an "if-then-else" in Simfony. |
| 33 | + |
| 34 | +```rust |
| 35 | +let bit_flip: bool = match false { |
| 36 | + false => true, |
| 37 | + true => false, |
| 38 | +}; |
| 39 | +``` |
| 40 | + |
| 41 | +Optional values can be matched. |
| 42 | +The `Some` arm introduces a variable which must be explicitly typed. |
| 43 | + |
| 44 | +```rust |
| 45 | +let unwrap_or_default: u32 = match Some(42) { |
| 46 | + None => 0, |
| 47 | + Some(x: u32) => x, |
| 48 | +}; |
| 49 | +``` |
| 50 | + |
| 51 | +Finally, `Either` values can be matched. |
| 52 | +Again, variables that are introduced in match arms must be explicitly typed. |
| 53 | + |
| 54 | +```rust |
| 55 | +let map_either: u32 = match Left(1337) { |
| 56 | + Left(x: u32) => f(x), |
| 57 | + Right(y: u32) => f(y), |
| 58 | +}; |
| 59 | +``` |
| 60 | + |
| 61 | +Match expressions don't support further pattern matching, in contrast to Rust. |
| 62 | + |
| 63 | +```rust |
| 64 | +let unwrap_or_default: u32 = match Some((4, 2)) { |
| 65 | + None => 0, |
| 66 | + // this doesn't compile |
| 67 | + Some((y, z): (u16, u16)) => <(u16, u16)>::into((y, z)), |
| 68 | +}; |
| 69 | +``` |
| 70 | + |
| 71 | +However, the match arm can contain code that performs the deconstruction. |
| 72 | +For example, the tuple `x` of type `(u16, u16)` can be deconstructed into two integers `y` and `z` of type `u16`. |
| 73 | + |
| 74 | +```rust |
| 75 | +let unwrap_or_default: u32 = match Some((4, 2)) { |
| 76 | + None => 0, |
| 77 | + Some(x: (u16, u16)) => { |
| 78 | + let (y, z): (u16, u16) = x; |
| 79 | + <(u16, u16)>::into((y, z)) |
| 80 | + } |
| 81 | +}; |
| 82 | +``` |
| 83 | + |
| 84 | +The match arm can also contain match expressions for further deconstruction. |
| 85 | +For example, the sum value `x` of type `Either<u32, u32>` can be matched as either `Left(y: u32)` or `Right(z: u32)`. |
| 86 | + |
| 87 | +```rust |
| 88 | +let unwrap_or_default: u32 = match Some(Left(42)) { |
| 89 | + None => 0, |
| 90 | + Some(x: Either<u32, u32>) => match x { |
| 91 | + Left(y: u32) => y, |
| 92 | + Right(z: u32) => z, |
| 93 | + }, |
| 94 | +}; |
| 95 | +``` |
0 commit comments