Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add StreamingIteratorMut and DoubleEndedStreamingIteratorMut #23

Merged
merged 3 commits into from
Jun 29, 2022

Conversation

cuviper
Copy link
Collaborator

@cuviper cuviper commented May 21, 2021

pub trait StreamingIteratorMut: StreamingIterator {
    fn get_mut(&mut self) -> Option<&mut Self::Item>; // required

    fn next_mut(&mut self) -> Option<&mut Self::Item>;

    fn fold_mut<B, F>(mut self, init: B, mut f: F) -> B
    where
        Self: Sized,
        F: FnMut(B, &mut Self::Item) -> B;

    fn for_each_mut<F>(self, mut f: F)
    where
        Self: Sized,
        F: FnMut(&mut Self::Item);

    fn map_deref_mut<B, F>(self, f: F) -> MapDerefMut<Self, F>
    where
        Self: Sized,
        F: FnMut(&mut Self::Item) -> B;
}

pub trait DoubleEndedStreamingIteratorMut:
    DoubleEndedStreamingIterator + StreamingIteratorMut
{
    fn next_back_mut(&mut self) -> Option<&mut Self::Item>;

    fn rfold_mut<B, F>(mut self, init: B, mut f: F) -> B
    where
        Self: Sized,
        F: FnMut(B, &mut Self::Item) -> B;
}

pub fn convert_mut<'a, I, T: ?Sized>(iterator: I) -> ConvertMut<'a, I::IntoIter, T>
where
    I: IntoIterator<Item = &'a mut T>;

In addition, these traits are implemented by all existing types that are able.

Fixes #21.

@cuviper
Copy link
Collaborator Author

cuviper commented May 22, 2021

BTW, it occured to me that StreamingIterator::get is similar to Peekable::peek. It follows that this new StreamingIteratorMut::get_mut is like Peekable::peek_mut, which will be stable in Rust 1.53.

@arturoc
Copy link

arturoc commented Jul 6, 2021

I've been using this for a while now and I've found find_mut to be useful as well. Even if the find borrow is not mutable the returned one can be mutable which allows to find an element and change it afterwards

#[inline]
    fn find_mut<F>(&mut self, mut f: F) -> Option<&mut Self::Item>
    where
        Self: Sized,
        F: FnMut(&Self::Item) -> bool,
    {
        loop {
            self.advance();
            match self.get() {
                Some(i) => if f(i) {
                    break;
                },
                None => break,
            }
        }

        (*self).get_mut()
    }

@cuviper
Copy link
Collaborator Author

cuviper commented Jul 7, 2021

Hmm, you could also write iter.find(...); iter.get_mut() since it won't have advanced any further. Then we can avoid the question of whether a find_mut closure should take a mutable reference. Does that work for you?

@arturoc
Copy link

arturoc commented Jul 8, 2021

it does what i need, once you know it, but I doubt most people using the crate would come to the conclusion that you can do that.

@arturoc
Copy link

arturoc commented Jul 8, 2021

Also I think the non mutable borrow is coherent with something like: vec.iter_mut().find()

@cuviper
Copy link
Collaborator Author

cuviper commented Jul 8, 2021

I don't know, that pattern has more possibilities too, so maybe we should teach it. For example, a hypothetical nth_mut can be done with nth+get_mut. Or you can get an index from position followed by either get or get_mut for the corresponding item, rather than enumerate (which we don't have) and find.

@arturoc
Copy link

arturoc commented Jul 9, 2021

Yes that makes sense perhaps it's just a matter of showing it in the documentation

These are extensions of their non-`Mut` counterparts, in short:

```rust
pub trait StreamingIteratorMut: StreamingIterator {
    fn get_mut(&mut self) -> Option<&mut Self::Item>;

    fn next_mut(&mut self) -> Option<&mut Self::Item>;

    fn fold_mut<B, F>(mut self, init: B, mut f: F) -> B
    where
        Self: Sized,
        F: FnMut(B, &mut Self::Item) -> B;

    fn for_each_mut<F>(self, mut f: F)
    where
        Self: Sized,
        F: FnMut(&mut Self::Item);
}

pub trait DoubleEndedStreamingIteratorMut:
    DoubleEndedStreamingIterator + StreamingIteratorMut
{
    fn next_back_mut(&mut self) -> Option<&mut Self::Item>;

    fn rfold_mut<B, F>(mut self, init: B, mut f: F) -> B
    where
        Self: Sized,
        F: FnMut(B, &mut Self::Item) -> B;
}
```

Only `get_mut` is required, and the rest have default implementations.

There is also a new conversion from `Iterator`:

```rust
pub fn convert_mut<'a, I, T: ?Sized>(iterator: I) -> ConvertMut<'a, I::IntoIter, T>
where
    I: IntoIterator<Item = &'a mut T>;
```
@cuviper cuviper merged commit 27ef010 into sfackler:master Jun 29, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Add get_mut
2 participants