Составление Option<Enum> с замыканиями, которые сопоставляют аргументы с образцом
У меня есть enum с двумя различными "типами" и функцией, которая может возвращать любой из них, завернутый в Option
:
enum Possibilities {
First(i32),
Second(String),
}
use Possibilities::*;
fn some_poss() -> Option<Possibilities> {
Some(Second(String::from("hi")))
}
Я хочу применить операцию к результату some_poss
, но эта операция имеет смысл только для одной из возможностей перечисления, в противном случае она должна вернуться 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);
1 ответ
Лучший способ справиться с этим конкретным случаем - создать метод на 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()
получает Option<i32>
От этого Possibilities
, а потом and_then
обвалы Option<Option<i32>>
в Option<i32>
,