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

时间:2015-02-21 18:17:27

标签: 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()])

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

附加说明

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

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

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

1 个答案:

答案 0 :(得分:8)

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

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

也就是说,您的函数需要的&String上的迭代变量类型为Stringfor i in vec!["foo".to_string()] { let () = i; // expected `collections::string::String`, // found `()` } 第二种情况也会发生同样的事情。第三种情况有效:

IntoIter

我们可以查看arraysall 3 forms of VecVec<T>的实施情况。请注意,&Vec<T> 的实现使用向量,而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()]); } 的实现必须通过对元素的引用返回迭代器。

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

以下是一个使用AsRef特征的示例,该特性可以达到您想要的效果:

Iterator

这表示我们期望任何实现特征AsRef<str>的具体类型。该迭代器必须产生一个实现特征String的类型,允许我们传入{&str,{{1}}}的{数组,向量,切片}。