[][src]Macro bind_match::bind_match

macro_rules! bind_match {
    ($expression: expr, $($pattern: pat)|+ $(if $guard: expr)? => $binding_expr: expr) => { ... };
    ($expression: expr, $($pattern: pat)|+ $(if $guard: expr)?) => { ... };
}

Works similarly to matches! but returns an Option of variables bound in the pattern.

The input of the macro looks like this:

bind_match!(input_expr, pattern => binding_expr)

Or with pattern guards:

bind_match!(input_expr, pattern if guard => binding_expr)

The binding_expr is returned, with variables bound in the pattern. If no binding expression is given then the result is Some(()).

Example

use bind_match::bind_match;

enum Foo {
    A(Option<i32>, bool),
    B { open: bool, closed: bool },
}
struct Bar {
    foo: Foo,
    fun: bool,
}

let bar = Bar {
    foo: Foo::A(Some(42), true),
    fun: false,
};
let result = bind_match!(bar, Bar { foo: Foo::A(Some(n), x), fun } if !fun => (n, x));
assert_eq!(result, Some((42, true)));

This can be particularly useful when matching inside iterator adapters. For example, using the same types as above:

fn fun_when_open(bars: impl IntoIterator<Item = Bar>) -> Option<bool> {
    bars.into_iter()
        .filter_map(|bar| bind_match!(bar, Bar { foo: Foo::B { open, .. }, fun } if open => fun ))
        .next()
}

The binding expression can be omitted, in which case it defaults to Some(()):

let bar = Bar {
    foo: Foo::A(Some(42), true),
    fun: false,
};
let result = bind_match!(bar, Bar { foo: Foo::A(Some(n), x), fun } if fun);
assert!(result.is_none());