How does flatten behave diffrently with Vec<Vec<_>> and Vec<Result<T<E>> or Vec<Option<T>> in rust

huangapple go评论72阅读模式
英文:

How does flatten behave diffrently with Vec<Vec<_>> and Vec<Result<T<E>> or Vec<Option<T>> in rust

问题

The official docs of iter::flatten state:

> 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 using entries.flatten() instead of the if-let block. However, in this context, there is no "nesting." 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 does flatten do here? How does it work?

英文:

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(&quot;/path/to/dir&quot;) {
        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?

答案1

得分: 2

>但这里并没有"嵌套",而是一个结果的迭代器

但是,Result实现了IntoIterator。这意味着你实际上有嵌套的迭代器...或者说,嵌套的项目_可以转化为迭代器_,这就是Iterator::flatten()对于迭代器项的所有要求:

where Self::Item: IntoIterator

Result&lt;T, E&gt;的实现在Ok时产生包含的T,在Err时不产生任何项。因此,Clippy是正确的--你可以使用Iterator::flatten来简化这段代码。

对于Option&lt;T&gt;也是一样的。当转换为迭代器时,如果是Some,它将产生包含的T,如果是None,则不产生任何项。

英文:

>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&lt;T, E&gt; 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&lt;T&gt;. When converted to an iterator, it will yield the contained T when Some and no items when None.

答案2

得分: 0

Result 也实现了 IntoIterator,具有一个迭代器,在 Ok 情况下产生一个元素,在 Err 情况下不产生任何元素,因此它有效。

英文:

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

答案3

得分: 0

"所以我的问题是,这里的flatten到底是做什么的?它是如何工作的?

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

所以flatten将主题迭代器的项目"链"在一起,如果它们是可迭代的(IntoIterator)。

ResultOption 实现了 IntoIterator,行为类似于具有值或无值/错误的0..=1元素的迭代器(取决于结果/选项是否具有值)。

因此,如果有值,它只是将Result替换为其项目(Ok),否则它会被剥离。这基本上就是你在这里做的事情,因此建议使用clippy。"

英文:

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

fn flatten(self) -&gt; Flatten&lt;Self&gt; 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.

huangapple
  • 本文由 发表于 2023年4月13日 14:39:39
  • 转载请务必保留本文链接:https://go.coder-hub.com/76002360.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定