如果Rust Option
提供了一些额外的便利方法,例如Option#flatten
和Option#flat_map
,其中flatten
会减少<Option<Option<T>>
,那将会很不错到Option<T>
,而flat_map
的工作方式与map
类似,但会采用返回Option
的方法/闭包并将其展平。
flat_map
非常简单:
fn opt_flat_map< T, U, F: FnOnce(T) -> Option<U> >(opt: Option<T>, f: F) -> Option<U> {
match opt {
Some(x) => f(x),
None => None
}
}
flatten
更复杂,而且我真的不知道如何定义它。它可能看起来像:
fn opt_flatten<T, U>(opt: Option<T>) -> Option<U> {
match opt {
Some( Some(x) ) => flatten_option( Some(x) ),
_ => opt
}
}
但这肯定不起作用。有什么想法吗?
另外,我如何在Option
枚举上实现这些方法,以便我可以在Option
实例上原生使用它们?我知道我需要在impl OptionExts for Option<T>
附近的某处添加类型签名,但我不知所措......
希望这是有道理的,我为我不精确的术语道歉 - 我是Rust的新手。
答案 0 :(得分:4)
这些可能已经存在,就像你期望的那样。查看docs for Option。
您会flat_map
更正常地看到and_then
:
let x = Some(1);
let y = x.and_then(|v| Some(v + 1));
做你想做的更大的方法是用你想要的方法声明 trait ,然后为Option
实现它:
trait MyThings {
fn more_optional(self) -> Option<Self>;
}
impl<T> MyThings for Option<T> {
fn more_optional(self) -> Option<Option<T>> {
Some(self)
}
}
fn main() {
let x = Some(1);
let y = x.more_optional();
println!("{:?}", y);
}
对于flatten
,我可能会写:
fn flatten<T>(opt: Option<Option<T>>) -> Option<T> {
match opt {
None => None,
Some(v) => v,
}
}
fn main() {
let x = Some(Some(1));
let y = flatten(x);
println!("{:?}", y);
}
但如果你想要一个特质:
trait MyThings<T> {
fn flatten(self) -> Option<T>;
}
impl<T> MyThings<T> for Option<Option<T>> {
fn flatten(self) -> Option<T> {
match self {
None => None,
Some(v) => v,
}
}
}
fn main() {
let x = Some(Some(1));
let y = x.flatten();
println!("{:?}", y);
}
是否有办法让平坦到任意深度
请参阅How do I unwrap an arbitrary number of nested Option types?
答案 1 :(得分:4)
fn flatten<T>(x: Option<Option<T>>) -> Option<T> {
x.unwrap_or(None)
}
就我而言,我正在处理Option
中的unwrap_or_else
- 返回方法,忘记了普通的or_else
方法。