#模式匹配 #模式 #枚举 #变体 #匹配 #

no-std try_match

具有函数样式的可错误模式匹配

9 个版本

0.4.2 2024 年 7 月 25 日
0.4.1 2023 年 5 月 18 日
0.3.0 2021 年 10 月 28 日
0.2.3 2021 年 10 月 26 日
0.1.0 2019 年 10 月 20 日

#171Rust 模式

Download history 10366/week @ 2024-04-21 7535/week @ 2024-04-28 6408/week @ 2024-05-05 6745/week @ 2024-05-12 6890/week @ 2024-05-19 7152/week @ 2024-05-26 8576/week @ 2024-06-02 11817/week @ 2024-06-09 8870/week @ 2024-06-16 7023/week @ 2024-06-23 7713/week @ 2024-06-30 6282/week @ 2024-07-07 5752/week @ 2024-07-14 7232/week @ 2024-07-21 9405/week @ 2024-07-28 7835/week @ 2024-08-04

每月 30,725 次下载
用于 21 个 crate (5 个直接使用)

MIT/Apache

24KB
151

try_match

docs.rs

具有函数样式的可错误模式匹配

基本用法

use try_match::{try_match, match_ok, unwrap_match};

#[derive(Copy, Clone, Debug, PartialEq)]
enum Enum { Var0, Var1(i32), Var2(i32, i32) }

use Enum::*;

// `try_match!` returns `Result`: `Ok(bindings)` on success or
// `Err(input_value)` otherwise
assert_eq!(try_match!(Var1(42), Var1(x)), Ok(42));
assert_eq!(try_match!(Var0,     Var1(x)), Err(Var0));

// `match_ok!` returns `Option`
assert_eq!(match_ok!(Var1(42), Var1(x)), Some(42));
assert_eq!(match_ok!(Var0,     Var1(x)), None);

// `match_or_default!` returns a default value on failure
assert_eq!(match_or_default!(Var1(42), Var1(x)), 42);
assert_eq!(match_or_default!(Var0,     Var1(x)), 0);

// `unwrap_match!` panics on failure:
assert_eq!(unwrap_match!(Var1(42), Var1(x)), 42);
        /* unwrap_match!(Var0,     Var1(x)); */ // this will panic

匹配守卫(if <expr>)受到支持

assert_eq!(match_ok!(Var1(42), Var1(x)),           Some(42));
assert_eq!(match_ok!(Var1(42), Var1(x) if x < 20), None);

绑定

// Returns `()` (wrapped by `Ok(_)`) if there are no bound variables
assert_eq!(unwrap_match!(Var1(42), Var1(_)), ());

// ... the bound value if there is exactly one binding
assert_eq!(unwrap_match!(Var1(42), Var1(x)), 42);

// ... an anonymous struct if there are multiple bindings
let vars = unwrap_match!(Var2(12, 34), Var2(a, b));
assert_eq!((vars.a, vars.b), (12, 34));

// ... or a tuple if the binding names are numeric
let (a, b) = unwrap_match!(Var2(12, 34), Var2(_0, _1));
assert_eq!((a, b), (12, 34));

// An optional `=>` clause specifies an explicit mapping
assert_eq!(unwrap_match!(Var1(42), Var1(x) => x + 1), 43);
assert_eq!(unwrap_match!(Var0,     Var0    => "yay"), "yay");

部分应用

// Omit the scrutinee expression to produce a closure
let _:             Option<i32> = match_ok!(Var1(42), Var1(x));
let _: fn(Enum) -> Option<i32> = match_ok!(        , Var1(x));

应用

迭代器::filter_map

let array = [Var1(42), Var0, Var1(10)];
let filtered: Vec<_> = array
    .iter()
    .filter_map(match_ok!(, &Var1(_0) if _0 > 20))
    .collect();
assert_eq!(filtered, [42]);

Iterator::map + 可错误 Iterator::collect

let array = [Var1(42), Var0, Var1(10)];
let filtered: Result<Vec<_>, _> = array
    .iter()
    .map(try_match!(, &Var1(_0) if _0 > 20))
    .collect();

// `Var0` is the first value that doesn't match
assert_eq!(filtered, Err(&Var0));

提取变体

impl Enum {
    fn var1(&self) -> Option<&i32> {
        match_ok!(self, Var1(_0))
    }

    fn is_var2(&self) -> bool {
        matches!(self, Var0)
    }
}

let enums = [Var1(42), Var0];
assert_eq!(enums[0].var1(), Some(&42));
assert_eq!(enums[1].var1(), None);

assert!(!enums[0].is_var2());
assert!(enums[1].is_var2());

期望特定变体

fn this_fn_expects_var2(foo: &Enum) {
    let i = unwrap_match!(foo, &Var2(42, _0));

    // Alternatively, you could use let-else (stabilized in Rust 1.65.0):
    // let &Var2(42, i) = foo else { panic!("{foo:?}") };

    assert_eq!(i, 84);
}

this_fn_expects_var2(&Var2(42, 84));

matcher::matches!(现在已纳入标准库作为 core::matches!)功能类似,但只返回 bool 值,表示匹配是否成功。

let success1 =  matches!(Some(42), Some(_));
let success2 = match_ok!(Some(42), Some(_)).is_some();
assert_eq!(success1, success2);

bind_match::bind_match!extract::extract! 的行为与 match_ok! 类似,但缺少隐式映射和部分应用。

variant::get_variant!extract_variant crate 提供与 match_ok! 类似的功能。它支持隐式映射,但使用不同的规则来处理多个绑定。

许可

MIT/Apache-2.0

依赖

~110KB