Add Vec::last_or_push and friends (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:

*x.last_mut_or_push(0) += 1;

which is much nicer.

Solution sketch

Add functions for Vec::last_or_push(T) -> &T, Vec::last_mut_or_push(T) -> &mut T, Vec::last_or_push_with(impl FnOnce() -> T) -> &T, Vec::last_mut_or_push_with(impl FnOnce() -> T) -> &mut T, which would get the last element of the vector, or push a value and return a reference to that.

Alternatives

Alternatively, Vec::push could return &mut T, which would remove the possiblity of a panic - maybe it would be better, but both would be nice. See issue #464.