I want to write a function that can work with the following types:
impl Iterator<Item = String>
impl Iterator<Item = &str>
The function is roughly like below:
use std::collections::HashMap;
fn make_hashmap(words: ???) {
let mut map: HashMap<String, usize> = HashMap::new();
for w in words {
// insert (w, length of w) into the map
}
}
I hope to allow callers to call my function in the following ways:
fn main() {
let some_data = vec!["Allen", "Bella", "Cathy"];
// Caller A
make_hashmap(&some_data);
// Caller B
make_hashmap(some_data.iter());
// Caller C
make_hashmap(some_data.into_iter());
// Caller D
make_hashmap("Allen Bella Cathy".split_whitespace());
}
As you can see, the function should support both consuming iterators and non-consuming iterators. And the iterator's element type should be able to be coverted into a String.
My attempt is like below:
use std::collections::HashMap;
fn make_hashmap(words: impl Iterator<Item = impl Into<String>>) {
let mut map: HashMap<String, usize> = HashMap::new();
for w in words {
let s = w.into();
let size = s.len();
map.insert(s, size);
}
}
However, it can only work with Caller C and Caller D, both being consuming iterators.
My motivation is to make my function as friendly as possible, such that callers can pass any iterable of string-like.