在《铁 rust 》中,我有一个枚举MatchType

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

我在我的compare函数中使用它来比较两个String.如果MatchTypeExact/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,
    }
}

但我想try 更简洁的方法:首先判断匹配项是否为这三个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.

我试着这样用pattern binding:

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个错误.有什么办法处理这件事吗?

推荐答案

这是不可能的.然而,这种模式(与另一个match中的部分值匹配)相当常见.通常,我在不可能的变量上看到它时会出现panic (unreachable!()),但返回缺省值也是可以的.

在这一领域有pattern types个作为试验性工作,可能会在future 的某个地方产生一些东西,但它仍处于规划阶段.

Rust相关问答推荐

从特征实现调用函数的Rust惯用方法

文档示例需要导入相关的 struct ,但仅在运行测试时.这是故意的行为吗?

通过解引用将值移出Box(以及它被脱糖到什么地方)?

在Rust中,如果Result是Err,运行副作用(如日志(log)记录)的惯用方法是什么

像这样的铁 rust 图案除了‘选项’之外,还有其他 Select 吗?

Gtk4-rs:将监视器作为gdk::monitor获取,而不是作为glib::对象获取

在生存期内将非静态可变引用转换为范围内的静态可变引用

有没有一种方法可以创建一个闭包来计算Rust中具有随机系数的n次多项式?

我们可以在 Rust 切片中使用步骤吗?

将 &str 或 String 保存在变量中

在没有任何同步的情况下以非原子方式更新由宽松原子操作 Select 的值是否安全?

如何为整数切片定义一个带有额外函数的特性别名?

Rust 中 Mutex<> 的深拷贝?

如何展平以下嵌套的 if let 和 if 语句?

第 7.4 章片段中如何定义 `thread_rng`

使用 `.` 将 T 转换为 &mut T?

以下打印数组每个元素的 Rust 代码有什么问题?

带有库+多个二进制文件的Cargo 项目,二进制文件由多个文件组成?

如何阅读 HttpRequest 主体

为移动和借位的所有组合实现 Add、Sub、Mul、Div