使用模式匹配参数的闭包组合 Option<Enum>

Composing Option<Enum> with closures that pattern-match arguments

我有一个枚举,其中包含两个不同的可能 "types" 和一个可能 return 其中任何一个的函数,包含在 Option:

enum Possibilities {
    First(i32),
    Second(String),
}
use Possibilities::*;

fn some_poss() -> Option<Possibilities> {
    Some(Second(String::from("hi")))
}

我想对 some_poss 的结果应用一个操作,但是这个操作只对枚举的一种可能性有意义,否则它应该 return None。例如:

let a: Option<i32> = some_poss().and_then(|poss| if let First(x) = poss {
    Some(x * 2)
} else {
    None
});

如何简洁地组合这个操作?可以这样写吗?

// Compile error: pattern `Second(_)` not covered
let b: Option<i32> = some_poss().map(|First(x)| x * 2);

处理这种特定情况的最佳方法是在 enum 上创建一个专门用于检索一个变体的方法。有点像 Result::ok.

enum Possibilities {
    First(i32),
    Second(String),
}
use Possibilities::*;

impl Possibilities {
    fn first(self) -> Option<i32> {
        match self {
            Possibilities::First(x) => Some(x),
            _ => None,
        }
    }
}

这样您就可以像这样实现您的功能:

some_fun().and_then(|p| p.first()).map(|x| x * 2)
// or, if you prefer this style:
some_fun().and_then(Possibilities::first).map(|x| x * 2);

这使得每个步骤都在做什么 - some_poss 得到一个 Option<Possiblities>,然后 first() 从那个 Possibilities 得到一个 Option<i32>,然后然后 and_thenOption<Option<i32>> 折叠成 Option<i32>.