Pattern Matching is a powerful feature of many functional languages as it often allows branching to be handled very succinctly compared to using multiple
else style statements. However given enough options and "when" guards, Pattern Matching can also become verbose and difficult to understand at a glance.
When this happens F#'s Active Patterns can be a great way to give meaningful names to the matching logic, which simplifies the code and also enables reuse.
When guards let you add arbitrary conditionals
Cases are evaluated from top to bottom and the first match is used
In the following snippet, the last match will never be used:
x is anything that wasn't listed above
x = 1 and
x = 4 will hit their specific cases, while everything else will fall through to the default case
x is 4
Pattern matching can be useful to handle Options:
Pattern matching checks the entire domain is covered
yields a warning
C:\Program Files (x86)\Microsoft VS Code\Untitled-1(2,7): warning FS0025: Incomplete pattern matches on this expression. For example, the value 'false' may indicate a case not covered by the pattern(s).
This is because not all of the possible bool values were covered.
bools can be explicitly listed but ints are harder to list out
here we use the special
_ character. The
_ matches all other possible cases.
_ can get you into trouble
consider a type we create ourselves it looks like this
We might write a match with expession that looks like this
The above code makes sense. We are assuming if you aren't sober you should call an uber so we use the
_ to denote that
We later refactor our code to this
The F# compiler should give us a warning and prompt us to refactor our match expression to have the person seek medical attention. Instead the match expression silently treats the unconscious person as if they were only tipsy. The point is you should opt to explicitly list out cases when possible to avoid logic errors.