我可能看不到树林,但我想知道如何设计我的方法以防止硬集合类型,而不是Iterators。考虑这种方法。
pub fn print_strings(strings: Vec<String>) {
for val in strings.iter() {
println!("{}", val);
}
}
如果我想将HashSet
或HashMap
与use 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
游戏围栏(也用于查看冗长的编译器错误)
不幸的是,这似乎也无法解决问题。我错过了什么?
答案 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
就是那个东西
添加生命周期,你就可以了! :)
另外,我建议使用静态调度。您可以在我提供的示例中看到它。