Pattern Matching

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

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

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
  ;

Constructor Patterns

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
   ; 

Mixed Patterns

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

Error handling

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.