接受字符串迭代器的函数的正确签名

Sør*_*org 4 rust

我对用于生成字符串切片的迭代器的正确类型感到困惑。

fn print_strings<'a>(seq: impl IntoIterator<Item = &'a str>) {
    for s in seq {
        println!("- {}", s);
    }
}

fn main() {
    let arr: [&str; 3] = ["a", "b", "c"];
    let vec: Vec<&str> = vec!["a", "b", "c"];
    let it: std::str::Split<'_, char> = "a b c".split(' ');

    print_strings(&arr);
    print_strings(&vec);
    print_strings(it);
}
Run Code Online (Sandbox Code Playgroud)

使用<Item = &'a str>arrvec调用不会编译。相反,如果我使用<Item = &'a'a str>,它们可以工作,但it调用不会编译。

当然,我也可以使 Item 类型通用,然后做

fn print_strings<'a, I: std::fmt::Display>(seq: impl IntoIterator<Item = I>)
Run Code Online (Sandbox Code Playgroud)

但它变得愚蠢。当然必须有一个单一的规范“字符串值迭代器”类型?

log*_*yth 5

您所看到的错误预期,因为seq&Vec<&str>&Vec<T>农具IntoIteratorItem=&T,所以用你的代码,你结束了Item=&&str,你期待它是Item=&str在所有情况下。

执行此操作的正确方法是扩展Item类型,以便它可以同时处理&str &&str。您可以通过使用更多泛型来做到这一点,例如

fn print_strings(seq: impl IntoIterator<Item = impl AsRef<str>>) {
    for s in seq {
        let s = s.as_ref();
        println!("- {}", s);
    }
}
Run Code Online (Sandbox Code Playgroud)

这要求Item是您可以从中检索的东西,&str然后在您的循环.as_ref()中将返回&str您正在寻找的东西。

这也有额外的好处,您的代码也将Vec<String>与任何其他实现AsRef<str>.