Oba supports pattern matching on both literal values and data types using match expressions. Match expressions have the form:
match <value> | <pattern> = <expression> | <pattern> = <expression> ... ;
The rules for pattern matching are:
value
can be a literal or a variable.pattern
can be a literal or an instance of a data type (more on this below).Pattern order also matters: patterns are considered from top to bottom, and the first one that matches the value wins.
Literal patterns are the simplest: They match if the given value is equal to the literal:
match 1
| 1 = "one"
| 2 = "two"
;
The expression above always evaluates to “one”, because the literal pattern 1
always matches the value 1
.
Variable patterns are almost as simple as literal patterns: They match if the given value has the same value as the variable:
let x = 1
match 1
| x = "one"
| 2 = "two"
;
The expression above always evaluates to “one”, because the variable pattern
x
always matches the value stored in the variable x
, by definition.
Variable patterns are a good way to specify a catch-all pattern if none of the other patterns in the expression match a value:
let value = 3
match value
| 1 = "one"
| 2 = "two"
| value = "big number" // catch-all
;
You can use pattern matching to both detect an instance’s [data type] and grab the values stored in in its fields. For example:
data Shape = Square length | Rectangle width height
let shape = Rectangle(3, 4)
let area = match shape
| Square l = l * l
| Rectangle w h = w * h
;
A match expression can use many different patterns at once. Here’s an example that uses literal, variable, and constructor patterns all at once:
let value = Square(4)
let size = match value
| 1 = 1
| 2 = 2
| Square l = l * l
| Rectangle w h = w * h
| value = value
;
system::print("%(size)\n") // Prints: 16
It’s possible that none of the patterns in a match expression match the given value. In this case an error is raised at runtime. As a best practice, always use a catch-all, variable pattern when possible.