我对用于生成字符串切片的迭代器的正确类型感到困惑。
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>、arr和vec调用不会编译。相反,如果我使用<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)
但它变得愚蠢。当然必须有一个单一的规范“字符串值迭代器”类型?
您所看到的错误预期,因为seq是&Vec<&str>和&Vec<T>农具IntoIterator用Item=&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>.