为什么`Option`支持`IntoIterator`?

2024-05-19

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

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

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);
    }
}
error[E0308]: mismatched types
  --> src/main.rs:11:18
   |
11 |         take_str(&s); // Type mismatch: found type `&&[std::string::String]`
   |                  ^^ expected `str`, found `&[String]`
   |
   = note: expected reference `&str`
              found reference `&&[String]`

我正期待着s成为一个String,但实际上是&[String]。这是因为我的for循环正在迭代Option由返回Vec::get().

我还编写了以下代码,这表明for循环实际上是展开一个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?


有什么用例可以迭代Option?

简而言之,我最喜欢的原因是flatten https://doc.rust-lang.org/std/iter/trait.Iterator.html#method.flatten:

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

Rust 1.29之前,你可以使用flat_map https://doc.rust-lang.org/std/iter/trait.Iterator.html#method.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,它可以容纳零个或多个元素。在很多方面,Option is一个容器就像一个Vec!

实施IntoIterator allows Option参与更大份额的 API。

注意IntoIterator is also实施用于Result,出于类似的原因。

这非常令人困惑

是的,确实如此,这就是为什么 Clippy有它的绒毛 https://rust-lang.github.io/rust-clippy/master/index.html#for_loops_over_fallibles:

warning: for loop over `str_vec.get(0..3)`, which is an `Option`. This is more readably written as an `if let` statement
  --> src/main.rs:10:14
   |
10 |     for s in str_vec.get(0..3) {
   |              ^^^^^^^^^^^^^^^^^
   |
   = note: `#[warn(clippy::for_loops_over_fallibles)]` on by default
   = help: consider replacing `for s in str_vec.get(0..3)` with `if let Some(s) = str_vec.get(0..3)`
   = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#for_loops_over_fallibles

这表明有一些方法可以Option is not就像程序员的容器一样。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

为什么`Option`支持`IntoIterator`? 的相关文章

随机推荐