Using don't care in patterns

Sometimes, the trick that variable's names have of matching any value in a pattern would be useful, but we don't actually need the information that would be stored in the variable. For example, we might not care about the error value when matching Result, just the fact that there was an error. In that situation, we can use an _ symbol to indicate I don't care what this value is:

match might_fail(39) {
Ok(x) => { println!("Odd succeeded, name is {}", x.name) }
Err(_) => { println!("Odd failed! Woe is me.") }
}

That's the reason why _ by itself can not be used as a variable name: it has a special meaning of its own. We can match _ against any data value of any data type, even multiple times in the same expression, and the matched values will simply be ignored.

Matching a value to _ does not even move or copy the value. When we tell the compiler that we don't care about a value, it believes us. However, there's an intermediate level between a full variable and a don't care. If we start a variable name with an _ but continue on after that with a valid variable name, the named variable isn't a don't care but it is exempt from some compiler warnings.

For example, normally, the compiler would warn us if we received a value into a variable but then did nothing with it. Putting an _ at the start of the variable name means the compiler will not complain about that. Where _ by itself means I don't care about this value, starting a variable name with _ means it's okay if I don't use this value.

A common use for that is when we are designing for the future. We might anticipate that a function parameter or structure member will be useful in the future, so we put it in now, but don't use it yet. If we prefix the name with _, the compiler won't yell at us about it. Then, when the time comes to actually use it, we remove the _ so we benefit from all of the compiler's checks.

In the previous example, we used _ to match against the error value, meaning we don't care what the error value actually is, as long as it's an error. However, _ can match anything, which means we can also do this:

    match might_fail(39) {
Ok(x) => { println!("Odd succeeded, name is {}", x.name) }
_ => { println!("If none of the above patterns match, _ certainly will") }
}

Here, the last pattern in our match is an _, which matches anything while capturing no data at all. This is very much like putting else at the end of an if chain. Any match expression containing an _ pattern automatically covers the entire space of possible values, too, which means that, as long as there is a reasonable fallback action to take when none of the more precise patterns match, Rust won't complain to us that we're not covering all of the possibilities.

By the way, if we put a plain _ pattern anywhere but at the bottom of the match expression, Rust will warn us. This is a good thing, because any patterns under it will never, ever get a chance to match.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.16.79.147