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 Iterator
s 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