Подтвердить что ты не робот

Почему `Option` поддерживает` IntoIterator`?

Я пытался выполнить итерацию по подразделу вектора строк, т.е. подклассу 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]`
    }
}

Очевидно, я ожидал, что s будет String, но на самом деле &[String]. Это связано с тем, что цикл for 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?

4b9b3361

Ответ 1

Какой пример использования для итерации по 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)
}

Option можно рассматривать как контейнер, который может содержать ровно нуль или один элемент. Сравните это с 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.

Это показывает, что существуют способы, которыми Option не похож на контейнер для программиста.