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

Kyl*_*and 12 foreach optional rust

我试图迭代一个字符串向量的子部分,即一个子部分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); // Type mismatch: found type `&&[std::string::String]`
    }
}
Run Code Online (Sandbox Code Playgroud)

显然,我期待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]`
}
Run Code Online (Sandbox Code Playgroud)

但这令人难以置信的混乱; 我没想到(直到我编写这段代码并弄清楚它实际上在做什么),Option可以通过迭代来解开.为什么支持?有什么用例可以迭代Option

She*_*ter 14

有什么用例可以迭代Option

总之,我最喜欢的理由是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)
}
Run Code Online (Sandbox Code Playgroud)

Option可以被认为是一个可以容纳零个或一个元素的容器.将其与a进行比较Vec,它可以容纳零个或多个元素.在大集的方式,一个Option 集装箱就像一个Vec!

实现IntoIterator允许Option参与更大比例的API.

请注意,IntoIterator实施了Result,出于同样的原因.

但这令人难以置信的混乱

是的,这就是为什么Clippy 有一个皮棉:

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

这表明,有一些的办法Option喜欢一个程序员的容器.

  • 为什么`flat_map()`而不是`filter_map()`?我会说后者更适合这种情况...... (4认同)
  • @KyleStrand:一个友好的提示,"Box"总是在Rust中有一个对象,没有null`Box` :) (2认同)