macro_rules! polymatch { ($matching:expr; $($match_arms:tt)*) => { ... }; ($($tt:tt)*) => { ... }; }
Expand description
Match which expands top-level |
patterns to multiple match arms.
Clarification
“top-level |
patterns” means that the |
is not inside some other pattern.
E.g.: the pattern in Foo(x) | Bar(x) =>
is a top-level |
pattern.
E.g.: the pattern in (Foo(x) | Bar(x)) =>
is not a top-level |
pattern,
because the |
is inside parentheses.
Syntax
This uses a macro_rules!
-like syntax for the parameters of this macro
$matched_expression:expr;
$( $(|)? $($or_pattern:pat_param)|+ $(if $match_guard:expr)? => $arm_expr:expr ),*
$(,)?
example demonstrating all of this syntax
Examples
Basic
assert_eq!(debugify(Ok(3)), "3");
assert_eq!(debugify(Err("hello")), r#""hello""#);
fn debugify(res: Result<u32, &'static str>) -> String {
typewit::polymatch! {res;
Ok(x) | Err(x) => format!("{:?}", x)
}
}
The above invocation of polymatch
expands to:
match res {
Ok(x) => format!("{:?}", x),
Err(x) => format!("{:?}", x),
}
Full syntax
Example that uses all of the syntax supported by this macro.
assert_eq!(bar(Foo::Byte(3)), 6);
assert_eq!(bar(Foo::Byte(9)), 18);
assert_eq!(bar(Foo::Byte(10)), 10);
assert_eq!(bar(Foo::U16(3)), 6);
assert_eq!(bar(Foo::U16(9)), 18);
assert_eq!(bar(Foo::U16(10)), 10);
assert_eq!(bar(Foo::U32(3)), 0);
assert_eq!(bar(Foo::Long(3)), 0);
enum Foo {
Byte(u8),
U16(u16),
U32(u32),
Long(u64),
}
const fn bar(foo: Foo) -> u64 {
typewit::polymatch! {foo;
// top-level `|` patterns generate a match arm for every alternate pattern
| Foo::Byte(x)
| Foo::U16(x)
if x < 10
=> (x as u64) * 2,
Foo::Byte(x) | Foo::U16(x) => { x as u64 }
// `|` inside patterns behaves like in regular `match` expressions
(Foo::U32(_) | Foo::Long(_)) => 0
}
}
The above invocation of polymatch
expands to:
match foo {
Foo::Byte(x) if x < 10 => (x as u64) * 2,
Foo::U16(x) if x < 10 => (x as u64) * 2,
Foo::Byte(x) => { x as u64 }
Foo::U16(x) => { x as u64 }
(Foo::U32(_) | Foo::Long(_)) => 0
}