Make Vec::push return a &mut reference to the pushed value (original) (raw)
Proposal
Problem statement
Getting a reference to the value you just pushed to a vector requires an extra call and unwrap:
let mut v = Vec::new(); v.push(42); *v.last_mut().unwrap() = 43;
Motivating examples or use cases
I'm currently porting https://github.com/Naruyoko/OmegaNum.js/ to Rust, and this is a common pattern all over:x.array[i+1]=(x.array[i+1]||0)+1;
This is directly translated as
if x.is_empty() { x.push(0); } let last_mut = x.last_mut().unwrap(); *last_mut += 1;
With this, this could be the following:
let last_mut = x.last_mut().unwrap_or(x.push(0)); *last_mut += 1;
which is much nicer.
Solution sketch
Change Vec::push to return a reference to the pushed value:
pub fn push(&mut self, value: T) -> &mut T { let len = self.len; if len == self.buf.capacity() { self.buf.grow_one(); } unsafe { let end = self.as_mut_ptr().add(len); ptr::write(end, value); self.len = len + 1; &mut *end } }
Alternatives
Alternatively, Vec::last_or_push(default: T) -> &T, along with 3 other variations for mutability and laziness, could make the above translate in only one line - maybe it would be better, but both would be nice. See issue #465.