Pattern Matching

patterns_match

Felix provides 3 kinds of pattern matching: algebraic pattern matching, regular sequence matching and general LR parsing. This section only deals with algebraic pattern matching. Just as certain expressions terms are used to compose or construct new values, such as infix , for tuples, so pattern matching is the dual operation, and is used to untangle or destroy a value. Note the term destructor implies finding the component parts of a value, not actually destroying it, so the meaning is different to C++.

Algebraic Pattern Matching


Algebraic pattern matching matches the term structure of a value's type against a pattern for that type, resulting in the binding of pattern variables to subterms of the term. All of the following kinds of pattern matching can be combined arbitrarily. All algebraic pattern matches work with the base expression syntax:

match <m-expr> with
| <pattern1> =>  <r1-expr>
...
endmatch

The components of a pattern are:

Pattern
Meaning
literal
Matches its value, can be an integer, float or string
literal .. literal
Matches a value in the denoted range inclusively
_
Matches anything
?ident
Matches anything and binds variable ident to it
name pattern
Matches union constructor name
case i pattern Matches the i'th component of a sum
pattern,pattern,..
Matches tuples
pattern when cond Matches the pattern provided the condition is met, the condition may depend on pattern variables
pattern as name
Matches the pattern and binds name to it
pattern : type
pattern with a type annotation

Each pattern of match is considered in order, if a match is found the associated expression is the value of the match expression, with any occurenced of pattern variables replaced by the values bound to them.

If none of the match cases matches the expression the result is undefined. The current implementation generates an assert() to catch this error, which will be elided if the code is compiled with -DNDEBUG as usual.

Examples:

match 1,2,(3,4) with
| x?,_,(?a,?b) => x + a + b
endmatch

match Some "Hello" with
| None => ""
| Some ?x => x
endmatch

match 42 with
| ?x when x == 42 => x+1
| _ => 0
endmatch

Let expression

A popular shorthand of a single match is the let expression:

let pattern = value in expr

which is exactly equivalent to

match value with | pattern => expr endmatch

however, let if a low precedence prefix operator, so the bindings introduced remain in effect until the end of the expression.

Conditional expression

Another popular shorthand is the conditional expression:

if cond then et else ef endif

which is exactly equivalent to

match cond1 with
| case 1 => et  // case 1 is true
| case 0 => ef  // case 0 is false
endmatch

You can also include elif clauses in a conditional expression:

if1 cond then e1
elif cond2 then e2
..
else e
endif

which is equivalent to a match with nested terms. Note that conditional expressions require an else clause.