enums - 如何确保每个枚举变体都可以在编译时从特定函数返回?

标签 enums rust

我有一个枚举:

enum Operation {
    Add,
    Subtract,
}

impl Operation {
    fn from(s: &str) -> Result<Self, &str> {
        match s {
            "+" => Ok(Self::Add),
            "-" => Ok(Self::Subtract),
            _ => Err("Invalid operation"),
        }
    }
}

我想在编译时确保每个枚举变量都在 from 函数中处理。

为什么我需要这个?例如,我可能会添加一个 Product 操作,而忘记在 from 函数中处理这种情况:

enum Operation {
    // ...
    Product,
}

impl Operation {
    fn from(s: &str) -> Result<Self, &str> {
        // No changes, I forgot to add a match arm for `Product`.
        match s {
            "+" => Ok(Self::Add),
            "-" => Ok(Self::Subtract),
            _ => Err("Invalid operation"),
        }
    }
}

是否可以保证匹配表达式返回枚举的每个变体?如果不是,模仿这种行为的最佳方式是什么?

最佳答案

一个解决方案是使用宏生成整个枚举、变体和翻译臂:

macro_rules! operations {
    (
        $($name:ident: $chr:expr)*
    ) => {
        #[derive(Debug)]
        pub enum Operation {
            $($name,)*
        }
        impl Operation {
            fn from(s: &str) -> Result<Self, &str> {
                match s {
                    $($chr => Ok(Self::$name),)*
                    _ => Err("Invalid operation"),
                }
            }
        }
    }
}

operations! {
    Add: "+"
    Subtract: "-"
}

通过这种方式添加变体很简单,而且您不会忘记解析。这也是一个非常干的解决方案。

可以很容易地使用您以后肯定需要的其他功能(例如反向翻译)来扩展此构造,并且您不必复制解析字符。

playground

关于enums - 如何确保每个枚举变体都可以在编译时从特定函数返回?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58715081/

相关文章:

c# - HtmlAgilitypack 枚举所有类

c++ - 为什么我们不能使用两个不同的可互换枚举?作为函数参数?

java - 在抽象类中初始化 Enum 变量

javascript - 跨组件强制执行参数值限制

rust - 如何使用 Piston 创建全屏窗口?

Rust 函数指针逆变

java - 关于单例属性的问题

rust - 与 Rust 借用检查器战斗

testing - 如何测试 Rust 程序传递给另一个程序的参数?

sorting - 如何对带有 map 状闭包的Rust Vector进行排序?