首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >当给定的枚举不是某个变体时,我如何返回零?

当给定的枚举不是某个变体时,我如何返回零?
EN

Stack Overflow用户
提问于 2018-03-23 03:17:48
回答 2查看 1.4K关注 0票数 4

我定义了以下枚举:

代码语言:javascript
复制
#[derive(Debug, Copy, Clone)]
struct Core;

#[derive(Debug, Copy, Clone)]
struct Mem;

#[derive(Debug, Copy, Clone)]
pub enum Atag {
    Core(Core),
    Mem(Mem),
    Cmd(&'static str),
    Unknown(u32),
    None,
}

我想在这个枚举上实现一个函数,它“过滤掉”某些枚举值。我有以下几点:

代码语言:javascript
复制
impl Atag {
    /// Returns `Some` if this is a `Core` ATAG. Otherwise returns `None`.
    pub fn core(self) -> Option<Core> {
        match self {
            Atag::Core => Some(self),
            _ => None
        }
    }
}

我不知道为什么,但编译器抱怨道:

代码语言:javascript
复制
error[E0532]: expected unit struct/variant or constant, found tuple variant `Atag::Core`
  --> src/main.rs:17:13
   |
17 |             Atag::Core => Some(self),
   |             ^^^^^^^^^^ not a unit struct/variant or constant
help: possible better candidate is found in another module, you can import it into scope
   |
1  | use Core;
   |

我还尝试了一种比较方法:

代码语言:javascript
复制
pub fn core(self) -> Option<Core> {
    if self == Atag::Core {
        Some(self)
    } else {
        None
    }
}

但是编译器抱怨:

代码语言:javascript
复制
error[E0369]: binary operation `==` cannot be applied to type `Atag`
  --> src/main.rs:20:12
   |
20 |         if self == Atag::Core {
   |            ^^^^^^^^^^^^^^^^^^
   |
   = note: an implementation of `std::cmp::PartialEq` might be missing for `Atag`
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2018-03-23 03:50:00

我认为这只是模式匹配的一个限制,旨在防止意外行为。

类型为AtagCore的完整“定义”是Atag::Core(raw::Core)。显然,Core的内容与您无关,但是编译器需要知道所有事情都是“考虑到”的,因为编译器是规则的粘性者。解决这一问题的最简单方法是使用"anything模式“,_,就像您在匹配非Core变体时所做的那样。

代码语言:javascript
复制
impl Atag {
    /// Returns `Some` if this is a `Core` ATAG. Otherwise returns `None`.
    pub fn core(self) -> Option<Core> {
        match self {
            // The compiler now knows that a value is expected,
            // but isn't necessary for the purposes of our program.
            Atag::Core(_) => Some(self),
            _ => None
        }
    }
}

要忽略多个值,可以使用Something::Foo(_, _) --对变体中的每个值使用一个下划线,或者使用Something::Foo(..)来忽略所有内容。

记住,与其他语言不同,锈蚀枚举并不是不同类型的集合。与枚举值相关联的数据是它的一部分,就像结构的字段一样。所以self == Atag::Core不是一个有意义的语句,因为它忽略了与Core关联的数据。Foo(0)Foo(12)不同,即使它们都是Foo变体。

我还想指出if let,据我所知,它是最接近标准if语句的选项,而无需在Atag上定义自定义is_core函数(考虑到matchif let的存在,这基本上是不必要的)。

代码语言:javascript
复制
impl Atag {
    /// Returns `Some` if this is a `Core` ATAG. Otherwise returns `None`.
    pub fn core(self) -> Option<Core> {
        if let Atag::Core(_) = self {
            Some(self)
        } else {
            None
        }
    }
}
票数 5
EN

Stack Overflow用户

发布于 2018-11-20 13:13:15

我需要这样的东西来把函数很好地连接在一起。在这种情况下,您希望返回未包装的核心类型,而不仅仅是枚举。

我还发现不使用输入更容易,因此接受了一个&self参数并返回了一个Option<&Core>。但你可以两者兼得。

锈病公约as_X作为基于引用的转换,into_X作为消耗值的转换。例如:

代码语言:javascript
复制
impl Atag {
    fn as_core(&self) -> Option<&Core> {
        if let Atag::Core(ref v) = self {
            Some(v)
        } else {
            None
        }
    }
    fn into_core(self) -> Option<Core> {
        if let Atag::Core(v) = self {
            Some(v)
        } else {
            None
        }
    }
}

fn main() {
    let c = Atag::Core(Core {});
    let m = Atag::Mem(Mem {});
    assert_eq!(c.as_core().map(|cc| "CORE_REF"), Some("CORE_REF"));
    assert_eq!(m.as_core().map(|cc| "CORE_REF"), None);
    // Consume c - we cant use it after here...
    assert_eq!(c.into_core().map(|cc| "NOM NOM CORE"), Some("NOM NOM CORE"));
    // Consume m - we cant use it after here...
    assert_eq!(m.into_core().map(|cc| "NOM NOM CORE"), None);
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/49441847

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档