Rust Iterable as argument

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