-1

The official docs of iter::flatten states :

An iterator that flattens one level of nesting in an iterator of things that can be turned into iterators.

But for this code:

if let Ok(entries) = fs::read_dir("/path/to/dir") {
        for entry in entries {
            if let Ok(entry) = entry {
                // Do something
            }
        }
}

Clippy suggests to use entries.flatten() instead of if-let block, But here "nesting" is not there, instead it's an Iterator of Results. "Nesting" would look like an Iterator of Iterators.

There's no exclusive flatten() method implementation in ReadDir which is returned by fs::read_dir()

So my question is what exactly flatten do here? How does it work?

Chayim Friedman
  • 47,971
  • 5
  • 48
  • 77

3 Answers3

2

But here "nesting" is not there, instead it's an Iterator of Results

Ah, but Result implements IntoIterator. This means you do effectively have nested iterators... or rather, nested items that can be turned into an iterator which is all the bound on Iterator::flatten() requires of an iterator's items:

where Self::Item: IntoIterator

The implementation for Result<T, E> yields the contained T when Ok and yields no items when Err. Therefore, clippy is correct -- you can use Iterator::flatten to simplify this code.

And the same is true for Option<T>. When converted to an iterator, it will yield the contained T when Some and no items when None.

cdhowie
  • 158,093
  • 24
  • 286
  • 300
0

Result also implements IntoIterator, with an iterator that yields one element in the Ok case and nothing in the Err case, so it works.

Chayim Friedman
  • 47,971
  • 5
  • 48
  • 77
0

So my question is what exactly flatten do here? How does it work?

fn flatten(self) -> Flatten<Self> where
    Self: Sized,
    Self::Item: IntoIterator

So flatten "chains" the items of the subject iterator if they are iterable (IntoIterator).

Result and Option implement IntoIterator, behaving as iterators of 0..=1 elements (depending whether the result/option has a value or a none/error).

So it just replaces the Result by its item (Ok) if there is one, otherwise it's stripped. Which is essentially what you're doing here, hence the recommendation of clippy.

cafce25
  • 15,907
  • 4
  • 25
  • 31
Masklinn
  • 34,759
  • 3
  • 38
  • 57