It seems to me that last_mut( available via Deref trait) has the same functionality ( it returns a mut ref to the last element, or None if the Vec is empty ).
What am I missing?
[ Well it actually returns a PeekMut struct, I guess it has something to do with that, and the pop method in that, but I am still having trouble seeing why it is useful ]
From the linked issue it lets you remove the item you're peeking at if you so desire. You can write x.peek_mut().unwrap().pop() which you can't do with last_mut.
EDIT: you can't do that, but you can write PeekMut::pop(x.peek_mut().unwrap()) as corrected below ... I hope!
I think that the docs are a bit too sparse on this. Vec::peek_mut returns a PeekMut, which is a mutable view on the underlying Vec, not a mutable reference.
It also exposes an associated function pop(), which allows to remove the peeked element from the Vec.
This allows for something like:
#![feature(vec_peek_mut)]
use std::vec::PeekMut;
fn main() {
let mut elements = vec![123];
if let Some(peeked_mut) = elements.peek_mut() {
if *peeked_mut == 123 {
let removed = PeekMut::pop(peeked_mut);
dbg!(removed);
}
}
}
Alas, you cannot do this, because pop() is not a method, i.e. does not take self.
The docs and example should definitely be improved before stabilization. This method isn’t useful unless you want to conditionally pop from the Vec; if you just want to modify the last element if it exists, there’s already last_mut as you said.
It seems to me the straight-forward way to do that is something like ( pseudo-code )
let flag = { have a look at the last element, figure out if it should be popped }; if flag { pop the last element }
“flag” can of course be eliminated.
I don’t see the advantage in having peek_mut.
From the point of view of code readability, most people coming across it will not know what it is, will need to consult documentation, and go through the cycle of confusion I just went through.
Yeah, not only does peek_mut mean you only test is_empty once (in effect), it borrows the Vec mutably so the borrow checker will forbid you from accidentally modifying the vector between the test and the pop.
It's not quite the same thing though. There are three states: empty vector, last element doesn't satisfy predicate, last element satisfies predicate. pop_if returning None doesn't distinguish between the first two. This seems analogous to the Entry API.
Ok, I guess that is the answer, although of course result of the pop can be unwrapped, or matched etc. as normal. So the answer seems to be it isn’t really needed, but it has some utility. I am not entirely convinced it is a good idea though, but I guess that is a matter of taste.