我正在try 写一个特性,它允许我将多个嵌套的Option<Option<...<T>>>>"展开"到单个Option<T>,以便更好地使用我正在使用的API.我正在try 创建一个通用的解决方案,但我不知道如何使其工作.

这是我的许多try 之一:

trait UnwrapOption<T> {
    fn unwrap_opt(self) -> Option<T>;
}

impl<T> UnwrapOption<T> for Option<T> {
    fn unwrap_opt(self) -> Option<T> {
        self
    }
}

impl<T> UnwrapOption<T> for Option<Option<T>> {
    fn unwrap_opt(self) -> Option<T> {
        match self {
            Some(e) => e.unwrap_opt(),
            None => None,
        }
    }
}

fn main() {
    let x = Some(Some(Some(1)));
    println!("{:?}", x.unwrap_opt());
}
error[E0282]: type annotations needed
  --> src/main.rs:22:24
   |
22 |     println!("{:?}", x.unwrap_opt());
   |                      --^^^^^^^^^^--
   |                      | |
   |                      | cannot infer type for type parameter `T` declared on the trait `UnwrapOption`
   |                      this method call resolves to `Option<T>`

推荐答案

与其将嵌套选项(如other answer shows)展平,我建议不要将需要展平的Option<Option<T>>展平.在我见过的大多数情况下,这是因为有人在本应使用Option::and_then的时候滥用了Option::map:

fn main() {
    let input = user_input();

    let a = input.map(add1);
    // a is Option<Option<i32>>

    let b = input.and_then(add1);
    // a is Option<i32>
}

fn user_input() -> Option<i32> {
    Some(10)
}

fn add1(a: i32) -> Option<i32> {
    Some(a + 1)
}

记住Rust是一种静态类型的语言;你将永远知道筑巢的确切程度.

另见:

Rust相关问答推荐

如何优化小型固定大小数组中的搜索?

将大小为零的类型实例存储到空指针中

为什么我可以跟踪以前borrow 过的变量?房主在哪里?

获取与父字符串相关的&;str的原始片段

习语选项<;T>;到选项<;U>;当T->;U用From定义

返回Result<;(),框<;dyn错误>>;工作

链表堆栈溢出

Rust从关联函数启动线程

通过异常从同步代码中产生yield 是如何工作的?

使用 serde::from_value 反序列化为泛型类型

如何迭代存储在 struct 中的字符串向量而不移动它们?

unwrap 选项类型出现错误:无法移出共享引用后面的*foo

Rust中的一生语法有什么作用?

Rust 编译器不统一在 if let 表达式的分支中都 impl Future 的类型

是否可以通过可变引用推进可变切片?

当 T 不是副本时,为什么取消引用 Box 不会抱怨移出共享引用?

Rust 中 `Option` 的内存开销不是常量

为什么1..=100返回一个范围而不是一个整数?

有没有更好的方法来为拥有 DIsplay 事物集合的 struct 实现 Display?

在 Rust 中组合特征的不同方法是否等效?