Provides expression macros to match a pattern on a given expression.
```rust use trymatch::{trymatch, matchok, unwrapmatch};
enum Enum
use Enum::{Var1, Var2};
// try_match!
returns Result
: Ok(bindings)
on success or
// Err(input_value)
otherwise
asserteq!(trymatch!(Var1(42), Var1(x)), Ok(42));
asserteq!(trymatch!(Var1(42), Var1(x) if x < 20), Err(Var1(42)));
// match_ok!
returns Option
asserteq!(matchok!(Var1(42), Var1(x)), Some(42));
asserteq!(matchok!(Var1(42), Var1(x) if x < 20), None);
// unwrap_match!
panics on failure:
asserteq!(unwrapmatch!(Var1(42), Var1(x)), 42);
unwrap_match!(Var1(42), Var1(x) if x < 20); // will panic
```
``rust
// Returns
()(wrapped by
Ok()`) if there are no bound variables
asserteq!(unwrapmatch!(Var1(42), Var1()), ());
// ... the bound value if there is exactly one binding asserteq!(unwrapmatch!(Var1(42), Var1(x)), 42);
// ... an anonymous struct if there are multiple bindings let vars = unwrapmatch!(Var1((12, 34)), Var1((a, b))); asserteq!((vars.a, vars.b), (12, 34));
// ... or a tuple if the binding names are numeric let (a, b) = unwrapmatch!(Var1((12, 34)), Var1((0, 1))); asserteq!((a, b), (12, 34));
// An optional =>
clause specifies an explicit mapping
asserteq!(unwrapmatch!(Var1(42), Var1(x) => x + 1), 43);
asserteq!(unwrapmatch!(Var2::
rust
// Omit the scrutinee expression to produce a closure
let _: Option<i32> = match_ok!(Var1(42), Var1(x));
let _: fn(Enum<i32>) -> Option<i32> = match_ok!( , Var1(x));
Iterator::filter_map
rust
let array = [Var1(42), Var2, Var1(10)];
let filtered: Vec<_> = array
.iter()
.filter_map(match_ok!(, &Var1(_0) if _0 > 20))
.collect();
assert_eq!(filtered, [42]);
Iterator::map
+ Fallible Iterator::collect
```rust
let array = [Var1(42), Var2, Var1(10)];
let filtered: Result
// Var2
is the first value that doesn't match
assert_eq!(filtered, Err(&Var2));
```
```rust
impl
fn is_var2(&self) -> bool {
matches!(self, Var2)
}
}
let enums = [Var1(42), Var2]; asserteq!(enums[0].var1(), Some(&42)); asserteq!(enums[1].var1(), None);
assert!(!enums[0].isvar2()); assert!(enums[1].isvar2()); ```
```rust fn thisfnexpectsvar1(foo: &Enum<[u8; 4]>) { let (i0, i1) = unwrapmatch!(foo, &Var1([_0, _, _, _1]));
// Alternatively, you could use let-else (stabilized in Rust 1.65.0):
// let &Var1([i0, _, _, i1]) = foo else { panic!("{foo:?}") };
assert_eq!((i0, i1), (42, 45));
}
thisfnexpects_var1(&Var1([42, 43, 44, 45])); ```
[matcher::matches!
][] (now incorporated into the standard library as
[core::matches!
][]) is similar but only returns bool
indicating whether
matching was successful or not.
rust
let success1 = matches!(Some(42), Some(_));
let success2 = match_ok!(Some(42), Some(_)).is_some();
assert_eq!(success1, success2);
[bind_match::bind_match!
][] and [extract::extract!
][] behave in the same way
as match_ok!
except for the lack of implicit mapping and partial application.
[variant::get_variant!
][] from the extract_variant
crate offers a similar
functionality to match_ok!
. It supports implicit mapping but uses different
rules to handle multiple bindings.
MIT/Apache-2.0