为什么`Option`支持`IntoIterator`? [英] Why does `Option` support `IntoIterator`?

查看:105
本文介绍了为什么`Option`支持`IntoIterator`?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图遍历字符串向量的一个子部分,即Vec<String>的子切片.在每次迭代中,我都希望将字符串作为切片传递给函数.

I was trying to iterate over a subsection of a vector of strings, i.e. a subslice of Vec<String>. Within each iteration, I wanted to pass the string as a slice to a function.

我没有注意到Vec::get返回一个Option,并认为我可以直接迭代返回值:

I didn't notice that Vec::get returns an Option, and thought I could just directly iterate over the return value:

fn take_str(s: &str) {
    println!("{}", s);
}

fn main() {
    let str_vec: Vec<String> =
        ["one", "two", "three", "uno", "dos", "tres"].iter().map(|&s| 
        s.into()).collect();
    for s in str_vec.get(0..3) {
        take_str(&s); // Type mismatch: found type `&&[std::string::String]`
    }
}

很明显,我期望sString,但实际上是&[String].这是因为我的for循环实际上是在Vec::get()返回的Option上进行迭代.

Clearly, I was expecting s to be a String, but it's actually &[String]. This is because my for loop is actually iterating over the Option returned by Vec::get().

我还编写了以下代码,演示了for循环实际上正在展开Option:

I also wrote the following code, which demonstrates that the for loop is in fact unwrapping an Option:

let foo = Option::Some ( ["foo".to_string()] );
for f in foo {
    take_str(&f); // Same error as above, showing `f` is of type `&[String]`
}

但这令人难以置信.我从没想到(直到我写这段代码并弄清楚它实际在做什么),Option可以通过对其进行迭代进行解包.为什么支持?有什么用例可以迭代Option?

But this is incredibly confusing; I never expected (until I wrote this code and figured out what it's actually doing) that Option could be unwrapped by iterating over it. Why is that supported? What use case is there for iterating over an Option?

推荐答案

有什么用例可以遍历Option?

总而言之,我最喜欢的原因是 flatten :

My favorite reason, in a word, is flatten:

fn main() {
    let results = vec![Some(1), None, Some(3), None];
    let sum: i32 = results.into_iter().flatten().sum();
    println!("{}", sum)
}

在Rust 1.29之前,您可以使用 :

Before Rust 1.29, you can use flat_map:

fn main() {
    let results = vec![Some(1), None, Some(3), None];
    let sum: i32 = results.into_iter().flat_map(|x| x).sum();
    println!("{}", sum)
}

Option可以被认为是一个容器,它可以恰好容纳零个或一个元素.将其与Vec进行比较,该c可以容纳零个或多个元素.在许多方面,Option 是一个容器,就像Vec

Option can be thought of as a container that can hold exactly zero or one elements. Compare this to a Vec, which can hold zero or many elements. In a large set of ways, an Option is a container just like a Vec!

实施IntoIterator允许Option参与更大份额的API.

Implementing IntoIterator allows Option to participate in a larger share of APIs.

请注意,出于类似原因,IntoIterator也是 Result实现的.

Note that IntoIterator is also implemented for Result, for similar reasons.

但这令人难以置信

But this is incredibly confusing

是的,这就是为什么Clippy 为此有毛钱的原因:

Yes, it is, which is why Clippy has a lint for it:

warning: for loop over `str_vec.get(0..3)`, which is an `Option`.
         This is more readably written as an `if let` statement.

这表明Option在某些方面不是像程序员的容器一样.

This shows that there are ways that an Option is not like a container to a programmer.

这篇关于为什么`Option`支持`IntoIterator`?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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