As a long time Rust user and C/C++ skeptic, I totally get why C-style pre- and post-increment operators were not included in Rust -- their behavior is subtle and confusing, and their usage is uncommon enough to not warrant the syntax complexity. That said, recently I've written a fair amount of code where it would have been convenient to have a post-increment method on usize, like:
impl usize {
fn post_increment(&mut self, diff: Self) -> Self {
let before = *self;
*self += diff;
before
}
}
If one takes it as a given that this method is useful, the following methods seem valuable to maintain symmetry, in approximately decreasing order of importance:
{integer}.post_increment(&mut self, diff: Self) -> Self on other integral types.
@Centril points out (offline) that post_add (and presumably post_sub) might be a better name for this method. This seems reasonable to me, but names are not terribly interesting to me at this point. Please imagine your ideal name(s) for this method (/ these methods), and respond accordingly.
Can you say more about where you wanted to use these? Given that most loops in Rust use .. instead of ++, I can't say I've really missed them in the same way, especially since expression block scopes are a thing.
Where is it unacceptably painful to just put the += 1 on the next line?
Note that my proposed methods do not increment by 1; they take an argument by which to increment. I've used the more-verbose equivalent of post-increment recently when implementing the size_of and align_of phases of a compiler, which amount to iterating over a product's elements and incrementing an offset by the element's size. It wasn't unacceptably painful to write:
let my_offset = *current_offset;
*current_offset += my_size;
but it would have been more convenient to instead write:
let my_offset = current_offset.post_increment(my_size);
This is not a huge gripe, but it also doesn't seem like there would be a huge cost to make it go away.
A post-increment method which statically incremented by exactly one would be silly; you're right. for loops accomplish that fine.
These "post" methods already exist on atomics, e.g. AtomicUsize::fetch_add. But there they take an ordering as well. Also, std::mem::replace is similar.
Why not just make a trait with a blanket impl for T: AddAssign + Copy that does what you want?
I am often tempted to use std::mem::replace to do stuff like this but I think code that does more than one "thing" on a line is hard to read and maintain.
I could easily implement my own AddAssign trait, but that occupies an awkward space where it seems to trivial to publish as a library and depend on in the handful of projects where I'd want it, but too much boilerplate to want to duplicate in each of those projects.
In my opinion, post-increment is at least as useful as some of the operators currently exposed on integral types (e.g. borrowing_sub, next_multiple_of, ilog10). This is not to say that those operations don't belong in the standard library; I think they do; it's that I think post-increment also belongs in the standard library.