flatten在rust中与Vec〈Vec< _>>和Vec〈Result〈T< E>>或Vec〈Option< T>>的行为有何不同

lxkprmvk  于 2023-04-21  发布在  其他
关注(0)|答案(3)|浏览(186)

iter::flatten的官方文档指出:
一个迭代器,它将可转换为迭代器的内容的迭代器中的一个嵌套级别展平。
但对于此代码:

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

Clippy建议使用entries.flatten()而不是if-let块,但这里没有“嵌套”,而是结果的迭代器。“嵌套”看起来像迭代器的迭代器。
fs::read_dir()返回的ReadDir中没有独占的flatten()方法实现
所以我的问题是flatten在这里到底做了什么?它是如何工作的?

knsnq2tg

knsnq2tg1#

但是这里没有“嵌套”,而是一个结果的迭代器
啊,但是Result实现了IntoIterator。这意味着你实际上有嵌套的迭代器......或者更确切地说,嵌套的项 * 可以转换成迭代器 *,这是Iterator::flatten()对迭代器项的所有要求:

where Self::Item: IntoIterator

Result<T, E>的实现在Ok时产生包含的T,而在Err时不产生任何项。因此,clippy是正确的--您可以使用Iterator::flatten来简化此代码。
对于Option<T>也是如此。当转换为迭代器时,当Some时,它将产生包含的T,而当None时,没有项目。

cyej8jka

cyej8jka2#

Result也实现了IntoIterator,它有一个迭代器,在Ok的情况下只产生一个元素,而在Err的情况下不产生任何元素,所以它可以工作。

wqsoz72f

wqsoz72f3#

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

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

因此,如果主题迭代器的项是可迭代的(IntoIterator),则扁平化“链”这些项。
ResultOption实现了IntoIterator,表现为0..=1个元素的迭代器(取决于result/option是否有值或none/error)。
因此,如果有一个项(Ok),它就用它的项(Ok)替换Result,否则它就被剥离了。

相关问题