将迭代器作为参数传递给函数是反模式吗?

use*_*r89 4 rust

假设我有一个字符串,我在它的字符上创建一个迭代器(可循环、可查看):

let hello = "hello";
let mut iterator = hello.chars().cycle().peekable;
Run Code Online (Sandbox Code Playgroud)

我想弄清楚 的类型iterator是什么,所以我故意引入了一个错误:

let mut iterator: usize = hello.chars().cycle().peekable;

然后编译器告诉我右侧的类型是:

std::iter::Peekable<std::iter::Cycle<std::str::Chars<'_>>>
Run Code Online (Sandbox Code Playgroud)

哇,真是一口。如果我像这样定义一个函数:

fn foobar(x: std::iter::Peekable<std::iter::Cycle<std::str::Chars<'_>>>){
    // snip
}
Run Code Online (Sandbox Code Playgroud)

我收到这样的错误:

error: underscore lifetimes are unstable (see issue #44524)
Run Code Online (Sandbox Code Playgroud)

那么,如果我想将迭代器传递给函数,我应该怎么做呢?或者,这是我应该避免的事情吗?

Mat*_*tze 5

好的,这个问题有多个方面:

首先,您可以通过给它一个显式的生命周期来避免编译器错误:

fn foobar<'a>(mut x: std::iter::Peekable<std::iter::Cycle<std::str::Chars<'a>>>){
Run Code Online (Sandbox Code Playgroud)

对于第二个问题,无论这是否惯用,我都会说不,避免这种特定的方法。

您只能传入这个特定的迭代器链 - 其他的都是不可能的。但大多数时候,您的算法对特定组合不感兴趣,而不是“生成”字符的功能。使用泛型impl Trait替代(如果您可以使用 nightly rust)。

Impl Trait 是一项功能,允许隐藏所使用的特定类型。在撰写本文时,这一特定功能在几天前​​(在撰写本文时)已在参数位置中接受 impl 特征。我制作了这个快速草图用于演示目的,游乐场链接

#![feature(universal_impl_trait)]

fn main() {
    foo("hello".chars());
    foo("hello".chars().rev());
}

fn foo(x: impl Iterator<Item=char>) {
    let text: String = x.collect();
    println!("{}", &text)
}
Run Code Online (Sandbox Code Playgroud)

编辑:您也可以使用泛型,请参阅 nullqube 和 stefan 的评论

  • 我认为当存在完美的、稳定的替代方案时,您不应该给出依赖于实验性、不稳定功能的答案。 (6认同)