如何在 Option 上实现一些方便的方法(例如,flat_map、flatten)? [英] How to implement some convenient methods (e.g., flat_map, flatten) on Option?

查看:48
本文介绍了如何在 Option 上实现一些方便的方法(例如,flat_map、flatten)?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如果 Rust 的 Option 提供一些额外的便利方法,比如 Option#flattenOption#flat_map,那就太好了,其中 flatten 会将 > 减少到 Option,而 flat_map 会像 map,但采用返回 Option 并将其展平的方法/闭包.

flat_map 非常简单:

fn opt_flat_map选项<U>>(opt:选项<T>,f:F)->选项<U>{匹配选项{一些(x) =>f(x),无 =>没有任何}}

flatten 比较复杂,我真的不知道如何定义它.它可能看起来像:

fn opt_flatten(opt: Option) ->选项<U>{匹配选项{一些(一些(x))=>flatten_option( Some(x) ),_ =>选择}}

但这肯定行不通.有什么想法吗?

此外,我将如何在 Option 枚举上实现这些方法,以便我可以在 Option 实例上本地使用它们?我知道我需要在 impl OptionExts for Option 附近的某处添加类型签名,但我不知所措...

希望这是有道理的,我为我不准确的术语道歉——我是 Rust 的新手.

解决方案

这些可能已经存在,就像您期望的名称不同.检查文档的选项.

您会更正常地看到 flat_mapand_then:

let x = Some(1);让 y = x.and_then(|v| Some(v + 1));

做你想做的更大的方法是用你想要的方法声明一个 trait,然后为 Option 实现它:

trait MyThings {fn more_optional(self) ->选项<自己>;}实施<T>MyThings for Option{fn more_optional(self) ->选项<选项<T>>{一些(自己)}}fn 主(){让 x = Some(1);让 y = x.more_optional();println!("{:?}", y);}

对于flatten,我可能会写:

fn flatten(opt: Option>) ->选项<T>{匹配选项{无 =>没有任何,一些(v) =>Ⅴ、}}fn 主(){让 x = Some(Some(1));让 y = 展平(x);println!("{:?}", y);}

但是如果你想要一个特质:

trait MyThings{fn 展平(自我)->选项<T>;}实施<T>MyThings<T>对于 Option>{fn 展平(自我)->选项<T>{匹配自我{无 =>没有任何,一些(v) =>Ⅴ、}}}fn 主(){让 x = Some(Some(1));让 y = x.flatten();println!("{:?}", y);}

<块引用>

有没有办法允许展平到任意深度

请参阅如何解开任意数量的嵌套选项类型?

It would be nice if Rust's Option provided some additional convenience methods like Option#flatten and Option#flat_map, where flatten would reduce an <Option<Option<T>> to Option<T>, and flat_map would work like map, but takes a method/closure that returns an Option and flattens it.

flat_map is pretty straightforward:

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 is more complex, and I don't really know how to go about defining it. It might look something like:

fn opt_flatten<T, U>(opt: Option<T>) -> Option<U> {
  match opt {
      Some( Some(x) ) => flatten_option( Some(x) ),
      _ => opt
  }
}

But that certainly doesn't work. Any thoughts?

Also, how would I go about implementing these methods on the Option enum, so that I can use them natively on an Option instance? I know I need to add the type signature in somewhere around impl OptionExts for Option<T>, but I'm at a loss...

Hope this makes sense and I apologize for my imprecise terminology--I'm brand new to Rust.

解决方案

These probably already exist, just as different names to what you expect. Check the docs for Option.

You'll see flat_map more normally as and_then:

let x = Some(1);
let y = x.and_then(|v| Some(v + 1));

The bigger way of doing what you want is to declare a trait with the methods you want, then implement it for 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);
}

For flatten, I'd probably write:

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);
}

But if you wanted a trait:

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);
}

Would there be a way to allow flatten to arbitrary depth

See How do I unwrap an arbitrary number of nested Option types?

这篇关于如何在 Option 上实现一些方便的方法(例如,flat_map、flatten)?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆