如何最普遍地迭代具有给定类型的一系列项目?
How to most generically iterate a sequence of items with a given type?
下面的代码最能说明问题。
use std::iter::IntoIterator;
fn iterate<I: IntoIterator<Item=String>>(v: I) {
}
// iterate(&["foo".to_string()])
// error: type mismatch resolving `<&[collections::string::String; 1] as core::iter::IntoIterator>::Item == collections::string::String`:
// expected &-ptr,
// found struct `collections::string::String` [E0271]
// iterate(["foo".to_string()].iter())
// type mismatch resolving `<core::slice::Iter<'_, collections::string::String> as core::iter::IntoIterator>::Item == collections::string::String`:
// expected &-ptr,
// found struct `collections::string::String` [E0271]
// This works !
iterate(vec!["foo".to_string()])
我如何一般地迭代任何东西(具有给定的项目类型)?
补充说明
目的是允许此类函数的用户传入任何可以迭代或转换为迭代器的内容。
另外我觉得编译器错误中并没有真正描述实际问题 - 因为它看到的类型似乎与它显示的不同。
我正在使用rustc 1.0.0-nightly (522d09dfe 2015-02-19) (built 2015-02-19)
让我们看看第一个案例的类型:
for i in &["foo".to_string()] {
let () = i;
// expected `&collections::string::String`,
// found `()`
}
也就是说,您的迭代变量的类型是 &String
, 而不是 String
上的 ,正如您的函数所希望的那样。你的第二个案例也会发生同样的事情。第三种情况有效:
for i in vec!["foo".to_string()] {
let () = i;
// expected `collections::string::String`,
// found `()`
}
我们可以查看 IntoIter
对 arrays and for all 3 forms of Vec 的实现。请注意,Vec<T>
的实现使用 向量,而 &Vec<T>
的实现必须 return 对元素引用的迭代器。
您不能使用数组,因此迭代器必须始终 return 引用。
这是一个使用 AsRef
特性的示例,它应该可以满足您的要求:
use std::iter::IntoIterator;
fn iterate<I, S>(v: I)
where I: IntoIterator<Item=S>,
S: AsRef<str>
{}
fn main() {
iterate(&["foo"]);
iterate(&["foo".to_string()]);
iterate(["foo".to_string()].iter());
iterate(vec!["foo".to_string()]);
iterate(&vec!["foo".to_string()]);
}
这表示我们期望任何实现特征 Iterator
的具体类型。该迭代器必须产生一个实现特征 AsRef<str>
的类型,允许我们传入 {String
,&str
} 的 {arrays,vectors,slices}。
下面的代码最能说明问题。
use std::iter::IntoIterator;
fn iterate<I: IntoIterator<Item=String>>(v: I) {
}
// iterate(&["foo".to_string()])
// error: type mismatch resolving `<&[collections::string::String; 1] as core::iter::IntoIterator>::Item == collections::string::String`:
// expected &-ptr,
// found struct `collections::string::String` [E0271]
// iterate(["foo".to_string()].iter())
// type mismatch resolving `<core::slice::Iter<'_, collections::string::String> as core::iter::IntoIterator>::Item == collections::string::String`:
// expected &-ptr,
// found struct `collections::string::String` [E0271]
// This works !
iterate(vec!["foo".to_string()])
我如何一般地迭代任何东西(具有给定的项目类型)?
补充说明
目的是允许此类函数的用户传入任何可以迭代或转换为迭代器的内容。
另外我觉得编译器错误中并没有真正描述实际问题 - 因为它看到的类型似乎与它显示的不同。
我正在使用rustc 1.0.0-nightly (522d09dfe 2015-02-19) (built 2015-02-19)
让我们看看第一个案例的类型:
for i in &["foo".to_string()] {
let () = i;
// expected `&collections::string::String`,
// found `()`
}
也就是说,您的迭代变量的类型是 &String
, 而不是 String
上的 ,正如您的函数所希望的那样。你的第二个案例也会发生同样的事情。第三种情况有效:
for i in vec!["foo".to_string()] {
let () = i;
// expected `collections::string::String`,
// found `()`
}
我们可以查看 IntoIter
对 arrays and for all 3 forms of Vec 的实现。请注意,Vec<T>
的实现使用 向量,而 &Vec<T>
的实现必须 return 对元素引用的迭代器。
您不能使用数组,因此迭代器必须始终 return 引用。
这是一个使用 AsRef
特性的示例,它应该可以满足您的要求:
use std::iter::IntoIterator;
fn iterate<I, S>(v: I)
where I: IntoIterator<Item=S>,
S: AsRef<str>
{}
fn main() {
iterate(&["foo"]);
iterate(&["foo".to_string()]);
iterate(["foo".to_string()].iter());
iterate(vec!["foo".to_string()]);
iterate(&vec!["foo".to_string()]);
}
这表示我们期望任何实现特征 Iterator
的具体类型。该迭代器必须产生一个实现特征 AsRef<str>
的类型,允许我们传入 {String
,&str
} 的 {arrays,vectors,slices}。