# Post-increment method on numeric types?

**URL:** <https://internals.rust-lang.org/t/post-increment-method-on-numeric-types/19959>\
**Category:** language design\
**Created:** [December 2, 2023, 2:12am UTC](https://internals.rust-lang.org/t/post-increment-method-on-numeric-types/19959 "2023-12-02T02:12:38Z")\
**Posts on this page:** 10\
**Page:** 1

<div class="post-metadata">

**Author:** ![annydalch](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/annydalch/32/3592_2.png) [@annydalch](https://internals.rust-lang.org/u/annydalch)\
**Post date:** [December 2, 2023, 2:12am UTC](https://internals.rust-lang.org/t/post-increment-method-on-numeric-types/19959/1 "2023-12-02T02:12:38Z")

</div>

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:

```rust
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:

1. `{integer}.post_increment(&mut self, diff: Self) -> Self` on other integral types.
2. `{integer}.post_decrement(&mut self, diff: Self) -> Self`.
3. `{integer}.pre_(increment|decrement) (&mut self, diff: Self) -> Self`.
4. `{float}.(pre|post)_(increment|decrement) (&mut self, diff: Self) -> Self`.

All of these methods seem pretty straightforward, with obvious semantics and implementations.

(Aside: one might also desire variants of these methods for wrapping, saturating, checked &c arithmetic, but I'm less concerned about that.)

Have these methods been considered before? Is there any reason not to include them?

---

<div class="post-metadata">

**Author:** ![annydalch](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/annydalch/32/3592_2.png) [@annydalch](https://internals.rust-lang.org/u/annydalch)\
**Post date:** [December 2, 2023, 2:18am UTC](https://internals.rust-lang.org/t/post-increment-method-on-numeric-types/19959/2 "2023-12-02T02:18:36Z")

</div>

@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.

---

<div class="post-metadata">

**Author:** ![scottmcm](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/scottmcm/32/2355_2.png) [@scottmcm](https://internals.rust-lang.org/u/scottmcm)\
**Post date:** [December 2, 2023, 2:21am UTC](https://internals.rust-lang.org/t/post-increment-method-on-numeric-types/19959/3 "2023-12-02T02:21:43Z")

</div>

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?

---

<div class="post-metadata">

**Author:** ![annydalch](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/annydalch/32/3592_2.png) [@annydalch](https://internals.rust-lang.org/u/annydalch)\
**Post date:** [December 2, 2023, 2:25am UTC](https://internals.rust-lang.org/t/post-increment-method-on-numeric-types/19959/4 "2023-12-02T02:25:35Z")

</div>

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:

```rust
let my_offset = *current_offset;
*current_offset += my_size;

```

but it would have been more convenient to instead write:

```rust
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.

---

<div class="post-metadata">

**Author:** ![user16251](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/user16251/32/10186_2.png) [@user16251](https://internals.rust-lang.org/u/user16251)\
**Post date:** [December 2, 2023, 2:38am UTC](https://internals.rust-lang.org/t/post-increment-method-on-numeric-types/19959/5 "2023-12-02T02:38:47Z")

</div>

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.

---

<div class="post-metadata">

**Author:** ![user16251](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/user16251/32/10186_2.png) [@user16251](https://internals.rust-lang.org/u/user16251)\
**Post date:** [December 2, 2023, 3:23am UTC](https://internals.rust-lang.org/t/post-increment-method-on-numeric-types/19959/6 "2023-12-02T03:23:23Z")

</div>

> [@annydalch](#):
>
> Is there any reason not to include them?

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.

---

<div class="post-metadata">

**Author:** ![annydalch](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/annydalch/32/3592_2.png) [@annydalch](https://internals.rust-lang.org/u/annydalch)\
**Post date:** [December 4, 2023, 5:07pm UTC](https://internals.rust-lang.org/t/post-increment-method-on-numeric-types/19959/7 "2023-12-04T17:07:05Z")

</div>

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.

---

<div class="post-metadata">

**Author:** ![HjVT](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/hjvt/32/10365_2.png) [@HjVT](https://internals.rust-lang.org/u/HjVT)\
**Post date:** [December 4, 2023, 5:18pm UTC](https://internals.rust-lang.org/t/post-increment-method-on-numeric-types/19959/8 "2023-12-04T17:18:30Z")

</div>

I've occasionally had to write code in this form, when needing an iota like sequential IDs.

---

<div class="post-metadata">

**Author:** ![mu001999](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/mu001999/32/14473_2.png) [@mu001999](https://internals.rust-lang.org/u/mu001999)\
**Post date:** [December 5, 2023, 3:47am UTC](https://internals.rust-lang.org/t/post-increment-method-on-numeric-types/19959/9 "2023-12-05T03:47:50Z")

</div>

A general solution:

```rust
trait CombinatorRet {
    fn ret<T>(&self, x: T) -> T {
        x
    }
}

trait CombinatorThen: Sized {
    fn then<T>(self, _: T) -> Self {
        self
    }
}

impl<T> CombinatorRet for T {}
impl<T: Sized> CombinatorThen for T {}

fn foo(mut x: i32) -> i32 {
    x.then(x += 1).then(println!("{}", x))
}

fn bar(mut x: i32) -> i32 {
    (x += 1).ret(x).then(x += 1).then(println!("{}", x))
}

fn main() {
    println!("{}, {}", foo(1), bar(1));
}

```

---

<div class="post-metadata">

**Author:** ![system](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/system/32/14092_2.png) [@system](https://internals.rust-lang.org/u/system)\
**Post date:** [March 4, 2024, 3:47am UTC](https://internals.rust-lang.org/t/post-increment-method-on-numeric-types/19959/10 "2024-03-04T03:47:59Z")

</div>

Closed on March 4, 2024, 3:47am UTC

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.
