详尽的匹配模式绑定

问题描述 投票:0回答:2

在 Rust 中我有一个枚举

MatchType

enum MatchType {
    Exact,
    Lower,
    Greater,
    Other,
}

我将它用于我的

compare
函数来比较两个
String
。如果
MatchType
Exact/Lower/Greater
我想将
String
转换为
f64
并比较它们的值(如果
parse
失败,我认为比较结果是
false
)。

我可以使用一些样板代码轻松实现它,如下所示:

fn compare(str_one: String, str_two: String, match_type: MatchType) -> bool {
    match match_type {
        MatchType::Exact => {
            let f_one = str_one.parse::<f64>();
            let f_two = str_two.parse::<f64>();

            if let (Ok(f_one), Ok(f_two)) = (f_one, f_two) {
                f_one == f_two
            } else {
                false
            }
        },
        MatchType::Lower => {
            let f_one = str_one.parse::<f64>();
            let f_two = str_two.parse::<f64>();

            if let (Ok(f_one), Ok(f_two)) = (f_one, f_two) {
                f_one < f_two
            } else {
                false
            }
        },
        MatchType::Greater => {
            let f_one = str_one.parse::<f64>();
            let f_two = str_two.parse::<f64>();

            if let (Ok(f_one), Ok(f_two)) = (f_one, f_two) {
                f_one > f_two
            } else {
                false
            }
        },
        MatchType::Other => false,
    }
}

但我想尝试更简洁的方法:首先检查匹配是否是这三个

Exact/Lower/Greater
之一,然后解析字符串,然后像这样执行实际比较:

fn compare(str_one: String, str_two: String, match_type: MatchType) -> bool {
    match match_type {
        MatchType::Exact | MatchType::Lower | MatchType::Greater => {
            let f_one = str_one.parse::<f64>();
            let f_two = str_two.parse::<f64>();

            if let (Ok(f_one), Ok(f_two)) = (f_one, f_two) {
                match match_type {
                    MatchType::Exact => f_one == f_two,
                    MatchType::Lower => f_one < f_two,
                    MatchType::Greater => f_one > f_two,
                    // --- Non-exhaustive --- 
                    _ => false,
                }
            } else {
                false
            }
        },
        MatchType::Other => false,
    }
}

它可以工作,但内部匹配并不详尽,当然简单的

_ => false
修复了它,但我想知道是否可以以某种方式告诉 Rust 编译器,内部模式只是这 3 个枚举变体
Lower/Greater/Exact

我尝试使用模式绑定,如下所示:

fn compare(str_one: String, str_two: String, match_type: MatchType) -> bool {
    match match_type {
        float_match @ (MatchType::Exact | MatchType::Lower | MatchType::Greater) => {
            let f_one = str_one.parse::<f64>();
            let f_two = str_two.parse::<f64>();

            if let (Ok(f_one), Ok(f_two)) = (f_one, f_two) {
                match float_match {
                    MatchType::Exact => f_one == f_two,
                    MatchType::Lower => f_one < f_two,
                    MatchType::Greater => f_one > f_two,
                    // --- Non-exhaustive error here ---
                }
            } else {
                false
            }
        },
        MatchType::Other => false,
    }
}

但我仍然收到

non-exhaustive
错误。有什么办法处理吗?

rust pattern-matching
2个回答
0
投票

也许您可以保留样板

_ => false
原样,但这样就可以快捷地执行
if
语句

fn compare(str_one: String, str_two: String, match_type: MatchType) -> bool {
    match match_type {
        MatchType::Exact | MatchType::Lower | MatchType::Greater => {
            let f_one = str_one.parse::<f64>();
            let f_two = str_two.parse::<f64>();

            match (f_one, f_two, match_type) {
                (Ok(f_one), Ok(f_two), MatchType::Exact)   => f_one == f_two,
                (Ok(f_one), Ok(f_two), MatchType::Greater) => f_one > f_two,
                (Ok(f_one), Ok(f_two), MatchType::Lower)   => f_one < f_two,
                _ => false
            }
        },
        MatchType::Other => false,
    }
}

0
投票

这是不可能的。然而,这种模式(与另一个

match
内的部分值匹配)相当常见。通常我会在不可能的变体上感到恐慌(
unreachable!()
),但返回默认值也很好。

模式类型作为该领域的实验性工作,可能会在未来的某个地方产生一些东西,但仍处于规划阶段。

© www.soinside.com 2019 - 2024. All rights reserved.