如何使用Iterator特征构建通用API

时间:2015-08-22 20:21:21

标签: collections iterator rust traits

我可能看不到树林,但我想知道如何设计我的方法以防止硬集合类型,而不是Iterators。考虑这种方法。

pub fn print_strings(strings: Vec<String>) {
    for val in strings.iter() {
        println!("{}", val);
    }
}

如果我想将HashSetHashMapuse std::collections::*; fn main () { let strings = vec!("Foo", "Bar"); let mut more_strings = HashMap::new(); more_strings.insert("foo", "bar"); more_strings.insert("bar", "foo"); print_strings(&strings.iter()); print_strings(&more_strings.values()) } fn print_strings(strings: &Iterator<Item=&str>) { for val in strings { println!("{}", val); } } 一起使用,那么显然这不足。

所以,我试过这个:

asp.net webform

游戏围栏(也用于查看冗长的编译器错误)

http://is.gd/EYIK11

不幸的是,这似乎也无法解决问题。我错过了什么?

3 个答案:

答案 0 :(得分:7)

更好的是,你可以做到

fn print_strings<Iterable>(strings: Iterable)
    where Iterable: IntoIterator,
          Iterable::Item: AsRef<str>
{
    for val in strings {
        println!("{}", val.as_ref());
    }
}

(Kudos Shepmaster的改进。)

这意味着您可以使用&mut Iterator来调用此动态调度具体迭代器或静态调度的集合类型。此外,迭代器类型可以是任何可以简单地转换为&str的内容,包括但不限于&str&&str甚至String

print_strings(&strings);
print_strings(strings.iter().map(|s| s.to_owned()));
print_strings(vec![&&&&"xyz"]);
print_strings(strings);
print_strings(more_strings.values());

答案 1 :(得分:4)

当您在.iter()上致电Vec<T>时,您会收到Iterator<Item=&T>。因此,当您在.iter()上致电Vec<&str>时,您会获得Iterator<Item=&&str>,而不是Iterator<Item=&str>。您应该查看.cloned()的{​​{1}}方法,它应该有助于解决您的问题。

另外,请注意,为了迭代迭代器,你必须能够改变它(拥有迭代器或者有一个可变的引用)。因此,只有一个不可变的引用是有点无用的。我建议将迭代器值移动到print_strings而不是通过引用传递它。如果你想为此使用trait对象,可以使用Iterator来实现,但是将print_strings作为通用函数可能更容易。

答案 2 :(得分:4)

playpen
首先,您需要.execute(),但实际上是Iterator<Item=&str>。 然后,您尝试拨打Iterator<Item=&&str>,但.iter()没有此方法。 您只需删除Iterator调用并接收(并发送ofc).iter()以使&mut Iterator<...>循环工作(for循环需要一些实现for的内容,IntoIterator就是那个东西 添加生命周期,你就可以了! :)
另外,我建议使用静态调度。您可以在我提供的示例中看到它。