While looking at this axum crate example, I noticed a weird syntax in the function signature:
async fn create_user(
Json(payload): Json<CreateUser>,
) -> impl IntoResponse {
// blah blah
}
I eventually understood that Json<T>(pub T) is a newtype struct and wrapping Json(payload) means that we're extracting the T - we don't care about Json<T>, only the contained T.
I tested this out:
fn baz(Some(value): Option<i32>) {
println!("value = {}", value);
}
The compiler complains that None is not covered.
My questions are:
Why does the compiler accept this syntax for enums knowing that it will never work (i.e. there will always be a pattern that is not covered)?
Are there other places where pattern matching in function arguments is useful?
There is a distinction between refutable and irrefutable patterns.
You probably understand refutable patterns, i.e. patterns that can fail to match. These are typically tied to conditionals:
if let <PAT> = ...match ... { <PAT> => ... }while <PAT> = ...However, irrefutable patterns are perhaps more prevalent.
let <PAT> = ...for <PAT> in ...fn f(<PAT>: ...)|<PAT>| { ... }You may understand their more advanced usage as "destructuring" or "structured bindings". Irrefutable patterns can:
a&a{ field1, field2, ... }(a, b)_This is explained further in Patterns and Matching in the Rust book.
So in essence, a pattern can go in place of a function parameter, but the pattern must not fail. Using patterns for destructuring struct fields or tuples is very common, though probably moreso for closures than functions.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With