Rust Pattern Matching Is Beautiful
I’ve been working on a Rust side project lately and as I always do when I write Rust code, I find myself loving pattern matching even more than I did before. It seems like such a simple thing, sort of just a better if statement, but the more you use it, the more you realize just how powerful and elegant it really is.
One example from this project is the need to parse a piece of text to
determine if a user is adding or removing a tag. If they specify an
argument like +work
it means they are adding the work
tag, and -home
would indicate they are removing the home
tag.
This might look something like this:
pub fn parse_tag(text: &String) -> Option<(Operator, String)> {
let mut chars = text.chars();
let operator = match chars.next() {
Some('+') => Operator::Add,
Some('-') => Operator::Remove,
_ => return None,
};
return match chars.next() {
Some(' ') | None => None,
Some(_) => Some((operator, text[1..].to_string())),
};
}
In the first match
statement, we check the first character for the +
or
-
sign, and set the operator variable to the appropriate value. However,
if the first character is neither of those, the value is not a tag, and we
can return None
from within the match statement and the entire function
will stop. This might seem trivial, but the alternative is assigning the
operator variable to None
, then performing additional logic to return in
our function.
The second match
statement shows another great feature: multiple match
patterns. If there are no more characters in the text, or the next
character is whitespace, we want to return None
from our function.
However, we don’t have to list these as separate match “arms”, instead we
can combine them with |
keeping our code extremely simple and easy to
understand.