Nested patterns

We can use pattern matching to pull a value out of a complex data structure. As long as the pattern matches the data value, it doesn't matter how complex the pattern and value are. If we want to match a tuple of tuples and extract one particular value from one of the inner tuples, we can do it like this:

let (_, (_, x, _, _), _) = ((5, 6, 7), (8, 9, 10, 11), (12, 13, 14, 15));
println!("x is {}", x);

This pattern matches any tuple of three elements, where the second element is a nested tuple of four elements, and stores the second element of that nested tuple in the x variable, then prints out the value of x.

We could have been even more specific, and replaced some of those _ with more detailed sub-patterns to match. That would have given us a pattern that paid more attention to the first and/or last elements out the outer tuple, or the other elements of the inner tuple.

We can use the same technique to dig into other data types, too; it's not limited to tuples. For example, earlier we used pattern matching to check whether a function had succeeded or failed to run properly:

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

In that code, we just match the success value to the x variable, but what if we wanted to handle things differently depending on the details of the success value? We can do that by making the contained value match a more detailed sub-pattern:

match might_fail(38) {
Ok(DemoStruct {id: 38, name: ref name, probability: _}) => {
println!("Even succeeded with the proper id: name is {}", name)
}
Ok(DemoStruct {id: ref id, name: ref name, probability: _}) => {
println!("Even succeeded with the wrong id: id is {}, name is {}", id, name)
}
Err(_) => { println!("Even failed! Woe is me.") }
}

Here, we have a pattern that matches when the function returns a success and the success values is a DemoStruct with the proper ID, a second pattern that matches when the function return a success and the success value is a DemoStruct no matter what the ID is, and a third pattern that matches any error the function might return.

The first pattern matches the expected case. If it doesn't match, the second pattern matches, allowing us to deal with an unexpected result that is still technically reported as a success. If neither of those patterns match, the third one handles explicit errors.

If we compile this example, it works fine, but the compiler warns us that the name: in the first pattern and the id: and name: in the second pattern are redundant. That's because, when we are initializing a data structure or data structure pattern in Rust, we can leave out the destination name if it's the same as the source name. In other words, the second pattern could have been written like Ok(DemoStruct {ref id, ref name, probability: _}) and Rust still would have understood it, because id and name are the names of two of the structure's contained variables. The redundancy warning is just telling us that we wrote more than we needed to.
..................Content has been hidden....................

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