如何最一般地迭代具有给定类型的项目序列?

Byr*_*ron 5 rust

下面的代码最能说明问题.

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()])
Run Code Online (Sandbox Code Playgroud)

如何一般地迭代任何东西(使用给定的项目类型)?

补充说明

目的是允许这样的函数的用户传入可以迭代或转换为迭代器的任何东西.

此外,我感觉实际问题并没有在编译器错误中真正描述 - 因为它看到的类型似乎与它显示的不同.

我在用 rustc 1.0.0-nightly (522d09dfe 2015-02-19) (built 2015-02-19)

She*_*ter 8

让我们看一下第一种情况的类型:

for i in &["foo".to_string()] {
    let () = i;
    // expected `&collections::string::String`,
    // found `()`
}
Run Code Online (Sandbox Code Playgroud)

也就是说,你的迭代变量的类型&String,String,因为你的函数希望.第二种情况也会发生同样的事情.第三种情况有效:

for i in vec!["foo".to_string()] {
    let () = i;
    // expected `collections::string::String`,
    // found `()`
}
Run Code Online (Sandbox Code Playgroud)

我们可以看看IntoIterfor 数组Vec的所有3种形式的实现.请注意,对于实施Vec<T> 消费的载体,而一个&Vec<T>必须在该元素的引用返回一个迭代.

您不能使用数组,因此迭代器必须始终返回引用.

这是一个使用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()]);
}
Run Code Online (Sandbox Code Playgroud)

这表示我们期望任何实现该特征的具体类型Iterator.该迭代器必须产生一个实现性状的类型AsRef<str>,使我们能够在{阵列,载体,切片} {传递String,&str}.