This chapter continues the study of functional programming foundations that the previous chapter opened. It covers basic data pattern matching. Pattern matching is an essential feature-rich mechanism of powerful data processing that is embedded into the F# language's core.
A good grasp of the F# pattern matching features is an absolute must for an enterprise developer because most of the time, enterprise business is revolving around sophisticated data transformations in Line Of Business (LOB) applications (https://blogs.msdn.microsoft.com/dragoman/2007/07/19/what-is-a-lob-application/) and along Extract Transform Load (ETL) (https://en.wikipedia.org/wiki/Extract,_transform,_load) cycles in data warehousing and business analytics.
I intentionally narrowed down the subject of this chapter to basic pattern matching for a merely didactic reason. Usually, F# beginners first grasp pattern matching as an imperative switch on steroids or just a semantically equivalent way of coding lengthy if...then...elif...elif... ...else...
expressions. Then, they begin to recognize the role of pattern matching in data structures decomposition. And finally, the pattern matching knowledge acquisition gets completed with embracing active patterns.
The goal of this chapter is to provide you with a thorough grasp of the pattern matching features associated with the F# match
construction:
The decomposition abilities consideration is postponed until the coverage of the data structures in the upcoming chapters. Similarly, I will cope with active patterns when covering the advanced programming techniques of F#.
Explicit match
construction in F# belongs to control flow elements, along with if-then-else
, or while-do
. Of other F# bits and pieces, a match
is a relatively complicated combination of the following parts and governing rules:
match comparison-expression with | pattern-expression1 -> result-expression1 ......................................... | pattern-expressionN -> result-expressionN
It works in this manner, that is, comparison-expression
is juxtaposed with each pattern-expression
beginning with pattern-expression1
and goes down the list until either the first match occurs, or passing pattern-expressionN
still non-matched. If a match is found for pattern-expressionX
, then the result of the entire construction is the result of result-expressionX
. If no matches are found, then MatchFailureException
is thrown, indicating that the match cases were incomplete.
The key points of pattern matching that are often missing by F# beginners on the first read are as follows:
match
construction represents an expression, like any other F# construction excluding value binding. This means that the value of one and only one of result-expressions
will be taken for the value of the entire construction (given that a certain matching has indeed taken place).pattern-expression1
through pattern-expressionN
must share the same type, which is also the same with the type of comparison-expression
in order for the match
construction to compile.result-expression1
through result-expressionN
must share the same type in order for the match construction to compile.comparison-expression
not covered by any of the patterns will cause MatchFailureException
.|
), AND (&
), and a special when
guard.Now, I will walk you through the multiplicity of pattern kinds so that you get used to their broad repertoire and become comfortable with getting around match
expressions.