How do we break data types apart? We can use pattern matching.
match not true with
| true -> "nope"
| false -> "yep";;
- : string = "yep"
Here, we're matching the pattern not true. It works kind of similar to a switch statement.
let y = match 42 with
| a -> a (* we're introducing the varaible name "a" here*)
val y : int = 42
Here, we've matched against 42 with a pattern variable, a in this case.
By the way, each match item is called a branch.
let z = match "foo" with
| "bar" -> 0
| _ -> 1;;
val z : int = 1
In this example, _ is a wildcard. It matches anything. We can also use pattern matching with other types.
let a = match [] with
| [] -> "empty"
| _ -> "not empty";;
val a : string = "empty"
Here, OCaml matched the empty list [] with the empty list []. On the other hand, if we matched it with a non empty list, it would return "not empty".
let b = match [1; 2] with
| [] -> "empty"
| _ -> "not empty";;
val b : string = "not empty"
What if we want to do something more powerful?
match ["taylor"; "swift"] with
| [] -> "folklore"
| h :: t -> h (* does this look like h :: t? If so, return h *)
- : string = "taylor"
What if we tried to return t?
match ["taylor"; "swift"] with
| [] -> "folklore"
| h :: t -> t;;
File "[7]", line 3, characters 13-14:
3 | | h :: t -> t;;
^
Error: This expression has type string list
but an expression was expected of type string
Uh oh! That happens because t is a string list (["swift"]), while "folklore" is a string. We can fix this by making folklore a string list:
match ["taylor"; "swift"] with
| [] -> ["folklore"]
| h :: t -> t;;
- : string list = ["swift"]
We can also do this with tuples! Say we wanted to define a function to get the first item out of a 3-tuple:
let fst3 t =
match t with
| (a, b, c) -> a;;
val fst3 : 'a * 'b * 'c -> 'a = <fun>
fst3 (1, 2, 3);;
- : int = 1
What if we wanted to write a function that returns the name and the school year of a student, from our previous examples?
type student = {name : string; year: int};;
let rbg = {name = "Ruth Bader"; year = 1954};;
type student = { name : string; year : int; }
val rbg : student = {name = "Ruth Bader"; year = 1954}
let name_with_year s =
match s with
| {name; year} -> name ^ " '" ^ string_of_int (year mod 100);;
val name_with_year : student -> string = <fun>
name_with_year rbg;;
- : string = "Ruth Bader '54"