# pattern matching, refutable

## Patterns available in Erg

### variable pattern

``````# basic assignments
i = 1
# with type
i: Int = 1
# with anonymous type
i: {1, 2, 3} = 2

# functions
fn x = x + 1
# equals
fn x: Add(Int) = x + 1
# (anonymous) function
fn = x -> x + 1
fn: Int -> Int = x -> x + 1

# higher-order type
a: [Int; 4] = [0, 1, 2, 3]
# or
a: Array Int, 4 = [0, 1, 2, 3]
``````

### Literal patterns

``````# Raise a TypeError if `i` cannot be determined to be 1 at compile time.
# omit `_: {1} = i`
1 = i

# simple pattern matching
match x:
1 -> "1"
2 -> "2"
_ -> "other"

# fibonacci function
fib0 = 0
fib1 = 1
fibn: Nat = fibn-1 + fibn-2
``````

### constant pattern

``````cond=False
match! cond:
True => print! "cond is True"
_ => print! "cond is False"

PI = 3.141592653589793
E = 2.718281828459045
num = PI
name = match num:
PI -> "pi"
E -> "e"
_ -> "unnamed"
``````

### Refinement pattern

``````# these two are the same
Array(T, N: {N | N >= 3})
Array(T, N | N >= 3)

f M, N | M >= 0, N >= 1 = ...
f(1, 0) # TypeError: N (2nd parameter) must be 1 or more
``````

``````_ = 1
_: Int = 1
zero_ = 0
right(_, r) = r
``````

If not constrained by context, `_` is of type `Obj`.

### Variable length patterns

It is used in combination with the tuple/array/record pattern described later.

``````[i,...j] = [1, 2, 3, 4]
assert j == [2, 3, 4]
first|T|(fst: T, ...rest: T) = fst
assert first(1, 2, 3) == 1
``````

### Tuple pattern

``````(i, j) = (1, 2)
((k, l), _) = ((1, 2), (3, 4))
# If not nested, () can be omitted (1, 2 are treated as (1, 2))
m, n = 1, 2

f(x, y) = ...
``````

### array pattern

``````[i, j] = [1, 2]
[[k, l], _] = [[1, 2], [3, 4]]

length[] = 0
length[_, ...rest] = 1 + lengthrest
``````

#### record pattern

``````record = {i = 1; j = 2; k = 3}
{j; ...} = record # i, k will be freed

{sin; cos; tan; ...} = import "math"
{*} = import "math" # import all

person = {name = "John Smith"; age = 20}
age = match person:
{name = "Alice"; _} -> 7
{_; age} -> age

f {x: Int; y: Int} = ...
``````

### Data class pattern

``````Point = Inherit {x = Int; y = Int}
p = Point::{x = 1; y = 2}
Point::{x; y} = p

Nil T = Class Impl := Phantom T
Cons T = Inherit {head = T; rest = List T}
List T = Enum Nil(T), Cons(T)
List T.
first self =
match self:
_ -> ...
second self =
match self:
_ -> ...
``````

### enumeration pattern

*Actually, it's just an enumeration type

``````match x:
i: {1, 2} -> "one or two: \{i}"
_ -> "other"
``````

### range pattern

*Actually, it is just an interval type.

``````# 0 < i < 1
i: 0<..<1 = 0.5
# 1 < j <= 2
_: {[I, J] | I, J: 1<..2} = [1, 2]
# 1 <= i <= 5
match i
i: 1..5 -> ...
``````

### Things that aren't patterns, things that can't be patterned

A pattern is something that can be uniquely specified. In this respect pattern matching differs from ordinary conditional branching.

Condition specifications are not unique. For example, to check if the number `n` is even, the orthodox is `n % 2 == 0`, but you can also write `(n / 2).round() == n / 2`. A non-unique form is not trivial whether it works correctly or is equivalent to another condition.

#### set

There is no set pattern. Because the set has no way to uniquely retrieve the elements. You can retrieve them by iterator, but the order is not guaranteed.