How it works...
Ever since we came across pattern matching in the Scala programming language, we fell in love with its simplicity. As a major pillar of functional programming, the technique provides a quick way to transform values in various ways without sacrificing Rust's type safety.
The literal matches in Steps 2 and 7 are a great way to save on if-else chains. However, the most common matching is probably done to unpack Result or Option types for extracting the encapsulated values. While multiple matches are only possible using the | symbol , there are special operators to match to particular variations: ... denotes a range, while .. means to skip the remaining members of a struct. _ is almost always a wildcard for ignoring a particular thing and, as a match clause, it is a catch-all and should be placed last. In Step 3, we did a lot of unpacking of tuples; we skipped some of the matches using an _ in place of a variable name.
In a similar fashion, Step 4 sets up and uses Rust's mechanism to match properties inside types when using the match clause (also called destructuring). This feature supports nesting and lets us pick values and sub-structs out of a complex struct instance. Neat!
However, it is often not done with matching on the type and then working with the unpacked values only in the match arm. Instead, having the match conditions lined up is a much better way to deal with allowed values within types. Rust's match clause supports guards for exactly that reason. Step 5 shows what they are capable of.
Steps 8 and 9 both then show the use of the previously implemented match functions. We highly recommend going through some experiments yourself and seeing what changes. The typed matching allows for complex architectures without verbose safeguards or workarounds, which is exactly what we want!
We've successfully learned about complex conditions with pattern matching. Now, let's move on to the next recipe.