Hi,
Are there anyway in rust to pass kind of Iterable as method argument, to decouple collection behaviour to its implementation, so I can use any kind of collection either it is Vec, LinkedList or HashSet?
&Vec works perfectly fine, however it is just single implementation.
2 Likes
That would be accepting something that is T: IntoIterator
. An example is the Vec::splice method (the replace_with
argument takes any iterator).
2 Likes
If you want to pass an iterator generically
fn my_func(input: impl Iterator<Item=Whatever>) { .. }
if you want trait objects
fn my_func(input: dyn Iterator<Item=Whatever>) { .. }
if you want anything that can be consumed to create an iterator
fn my_func<I>(input: I)
where I: IntoIterator<Item=MyItem>
{
let mut iter = input.into_iter();
// ...
}
I've mixed and matched generics styles to show both ways,
If you want to iterate over a Vec
without consuming it, you probably want impl Iterator<Item=&'a MyItem>
EDIT see birkenfeld's comment below - IntoIterator
is strictly more general, but maybe Iterator shows intent better I'm not sure.
4 Likes
There's no need to use Iterator
instead of IntoIterator
and lose generality. There's a blanket impl impl IntoIterator for Iterator
.
2 Likes
IntoIterator it does work, however requires some magic with explicit lifecycles.
pub fn get_hashmap_values<'a,'b, K: 'b + Eq + Hash, V, II>(map: &'a mut HashMap<K, V>, keys: II) -> Result<Vec<&'a mut V>, String>
where II: IntoIterator<Item=&'b K>
Thanks