## Construct, Destruct

The `(a,b)`

operation **constructs** a tuple.

Suppose we want to access the first element of a tuple:

```
let m = ("UMTC", "CSCI", 1200)
let first_of_m = (* what goes here? *)
```

OCaml programs destructure, or **destruct** data, using *pattern matching*:

`let first_of_m = match m with (m1,m2,m3) -> m1`

## Match expression

```
match input_expr with
p1 -> e1
| p2 -> e2
| ...
```

Each match clause has the form `pattern -> body`

:

```
let grade_points g = match g with
| 'A' -> 4.0
| 'B' -> 3.0
| 'C' -> 2.0
```

Patterns can be constants, names, wild card `_`

, or constructed from patterns.

How did the definition `let pow (b,n) = ...`

work?

Another shorthand:

`fun x -> match x with (* clauses *) ≡ function (* clauses *)`

```
let rec fib = function
| 0 -> 0
| 1 -> 1
| n -> fib (n-1) + fib (n-2)
let rec sumup = function 0 -> 0 | n -> n + (sumup (n-1))
```

## “as” pattern

When a pattern has multiple possibilities we can bind a name to the expression with `as`

:

```
let rec leet_char = function
'A'..'Z' as c -> leet_char (char_of_int ((int_of_char c) + 32))
| 'l' -> '1'
| 'e' -> '3'
| 't' -> '7'
| s -> s
```

```
let imo = function
("Vikings" | "Gophers" | "Twins") as team -> team ^ " rule!"
| losers -> losers ^ " drool!"
```

Note: `match`

statements (and the `function...`

shorthand) use the *first* matching pattern:

```
let rec fib = function
n -> fib (n-1) + fib (n-2)
| 0 -> 0
| 1 -> 1
```

We can use patterns to combine multiple checks succinctly, e.g.:

```
let fizzorbuzz n = match (n mod 3, n mod 5) with
(0,0) -> "FizzBuzz\n"
| (0,_) -> "Fizz\n"
| (_,0) -> "Buzz\n"
| _ -> (string_of_int n)^"\n"
let rec fizzbuzz = function
| n when n <= 100 -> (fizzorbuzz n) ^ (fizzbuzz (n+1))
| 101 -> ""
| _ -> invalid_arg "fizzbuzz"
```

```
let rec strnums = function
| (m,n) when m < n -> (string_of_int m) ^ "," ^ (strnums (m+1,n))
| (m,n) when m = n -> string_of_int m
| _ -> ""
```

(Notice the **pattern guard** “`when`

`condition`

”…)

## Patterns, patterns, everywhere…

Patterns can also be used anywhere a name might be bound:

`let (x,y) = (2, "dos") in y`

`let (x,_) = (4, print_string "Hello!\n")`

`let (0 | 1 | 2) = read_int () in 42`