If `Iterator` is for "pulling out" data, then what is for "pushing in"?

The Iterator trait is essentially defined as follows:

pub trait Iterator {
    type Item;
    fn next(&mut self) -> Option<Self::Item>;
    // ...
}

and then there's a whole range of iterator adaptors. The iterator can be used to "read" data.

Now I was wondering if there is something similar to "write" data as follows:

pub trait Collector {
    type Item;
    fn append(&mut self, item: Item);
    // ...
}

I called it "Collector" for now, but I have no idea what the name would be: "Collector", or maybe "CoIterator", I don't know.

The idea is that by using this, I get a number of "collector adaptors" for free and I don't have to re-invent the wheel. Any thoughts or ideas?

1 Like

This is Extend. And there is also FromIterator that creates a new collection. The collect method uses it.

5 Likes

Thank you @Riateche for your answer! Extend can be used to, well, extend a collection if you already have an iterator. What I am looking for is something that can be used if you have only individual items, but no iterator over them.

I don't think such interface is provided as a trait (at least by std).
All std containers seems to provide single-element pushing-in feature as inherent methods.
Examples in std:

It seems that, push() is used if the order of pushed elements are preserved, and insert() when the order is not preserved.

1 Like

You can use iter::once to create an iterator from one item.

4 Likes

The async world has a type called Sink.

1 Like

I don't think there's a convenient way of "pushing in" more than one item. Where would you need that? I can't think of an example off the top of my head. Either you can express the data as an iterator over a regular pattern or file input etc., or you need to get each value and push it or insert it one by one via e.g. user input on the command line.

1 Like

Do you mean 'I don't think there's a convenient way of "pushing in" one item.'?
In this code, I define a trait that is essentially a special case (read: non-generic) of the Collector trait from my post earlier. I believed that I used it to push one item, but looking at the source code again, I see that I use it over here in, indeed, a loop over an iterator.

Again, assuming that you meant "pushing in", an example is a "callback". The source code that I referred to above is such an example. The reason why I work with an iterator is because the data is not handled immediately, but rather stored in a queue first.

I cannot mark more than one answer as a solution.

I think both the following are an answer:

and

1 Like

Sorry, I think you misunderstand what I meant because I wasn't very clear :slightly_frowning_face:

What I meant was: if you have a list of values you want to push into a collection, you'd anyway need to look at them one by one and push each one, whether by copying for Copy types or by moving for other types. So you will anyway need to create an iterator over your list and call a consumer method on the iterator.

If you want to push say 10 values provided by user input, you'd need to loop, ask for input, push that value, repeat until you have all ten. I can't see how you need a different way of pushing a lot of values. How would it even work?

I guess I was just confused by that. But it seems we misunderstood each other. I think we agree, although we didn't succeed to communicate that with each other very well :wink:

Is this question born out of the need to take a generic container in and populate it? If so, then this reddit discussion might be relevant: https://www.reddit.com/r/rust/comments/83q25s/why_no_traits_for_collections_in_rust/

1 Like

I highly suggest watching Erik Meijer's Playful Introduction to Rx, which is exactly about "inverting" iterators. I am not aware of the state of reactive programming in Rust, but this post suggests some projects that seem to fulfil your needs.

I have used custom Sink traits for this use case (sync and fallible trait for pushing in data). I think of it as a sort of fallible generalisation of passing a Vec that can be pushed into.