I may not see the forest for the trees but I wonder how do I actually design my methods to not work against hard collection types but against Iterators instead. Consider this method.
pub fn print_strings(strings: Vec<String>) {
for val in strings.iter() {
println!("{}", val);
}
}
Obviously this falls short if I want to use that with an HashSet or HashMap.
So, I tried this:
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);
}
}
Playpen (also to view lengthy compiler error)
http://is.gd/EYIK11
Unfortunately, this doesn't seem to do the trick either. What am I missing?
Even better, you can do
fn print_strings<Iterable>(strings: Iterable)
where Iterable: IntoIterator,
Iterable::Item: AsRef<str>
{
for val in strings {
println!("{}", val.as_ref());
}
}
(Kudos Shepmaster for the improvement.)
This means that you can call this with &mut Iterators for dynamic dispatch or concrete iterator or collection types for static dispatch. Further, the iterator type can be anything that can be simply converted to &str, which includes but is not limited to &str, &&str and even 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());
When you call .iter() on a Vec<T>, you get an Iterator<Item=&T>. So when you call .iter() on a Vec<&str>, you get an Iterator<Item=&&str>, not a Iterator<Item=&str>. You should look at the .cloned() method for Iterator, it should help solve your problem.
Also, note that in order to iterate through an iterator, you must be able to mutate it (either own the iterator or have a mutable reference to it). So just having an immutable reference to it is sorta useless. I would recommend moving the iterator value into print_strings rather than passing it by reference. If you want to use trait objects for this, you can do that by using Box, but it might be easier to just make print_strings a generic function.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With