Rust: Introduce post-increment like in C++

Created on 8 Feb 2014  Â·  15Comments  Â·  Source: rust-lang/rust

Instead of writing something like i += 1 one should be able to write i++

Most helpful comment

I don't think we should support i++. If we do, it would need to be an expression that returns the pre-incremented value, like it does in C, and that would therefore only be usable with implicitly-copyable types. But x += 1 can work with non-implicitly-copyable types, and I think it's a bad idea to have cases where x += 1 works but x++ doesn't.

All 15 comments

I'm ambivalent about a i++ operation that is solely sugar for the expression i += 1.

I'm pretty sure I _don't_ want a separate operator overload lang-item for i++ (as in, I would not be happy if i += 1 and i++ could mean different things depending on how one has implemented two distinct traits).

(edit: kballard points out below that the return values of i++ and of i += 1 differ; pre- versus post-increment. So I guess I should have said: i++ would need to be sugar for { let t = i; i += 1; t }.)

I don't think we should support i++. If we do, it would need to be an expression that returns the pre-incremented value, like it does in C, and that would therefore only be usable with implicitly-copyable types. But x += 1 can work with non-implicitly-copyable types, and I think it's a bad idea to have cases where x += 1 works but x++ doesn't.

I don't think there's a compelling reason to add this. It's extra syntax without much benefit, since += 1 is very short. Either way, this would need to go through the RFC process.

I don't think there's a compelling reason to add this

Syntactic sugar is a compelling reason. also it makes the language feel consistent and familiar to newcomers from any C style language.

Syntactic sugar is a compelling reason. also it makes the language feel consistent and familiar to newcomers from any C style language.

And that's an horror and lead to some misunderstanding. How many people knows the difference between:

int i = 0;

while (i++ < 10);

and:

int i = 0;

while (++i < 10);

Also, like said above, i++ returns a value whereas i += 1 doesn't.

make it so there is only one?

Alternatively allow operator overloading, Someone will implement it in
that case though generally one does not code in that style if they know
what's good for them.

On Tue, May 31, 2016 at 7:47 PM, Guillaume Gomez [email protected]
wrote:

Syntactic sugar is a compelling reason. also it makes the language feel
consistent and familiar to newcomers from any C style language.

And that's an horror and lead to some misunderstanding. How many people
knows the difference between:

int i = 0;
while (i++ < 10);

and:

int i = 0;
while (++i < 10);

Also, like said above, i++ returns a value whereas i += 1 doesn't.

—
You are receiving this because you commented.
Reply to this email directly, view it on GitHub
https://github.com/rust-lang/rust/issues/12111#issuecomment-222854362,
or mute the thread
https://github.com/notifications/unsubscribe/AFbiBuZLd4BEXQ_ukTRQBaNBopRYxGJeks5qHMingaJpZM4BgVOt
.

We have explicitly rejected ++X and X++ before.

On May 31, 2016, 20:18 -0400, Adam [email protected], wrote:

make it so there is only one?

Alternatively allow operator overloading, Someone will implement it in
that case though generally one does not code in that style if they know
what's good for them.

On Tue, May 31, 2016 at 7:47 PM, Guillaume [email protected]
wrote:

Syntactic sugar is a compelling reason. also it makes the language feel
consistent and familiar to newcomers from any C style language.

And that's an horror and lead to some misunderstanding. How many people
knows the difference between:

int i = 0;
while (i++<10);

and:

int i = 0;
while (++i<10);

Also, like said above, i++ returns a value whereas i += 1 doesn't.

—
You are receiving this because you commented.
Reply to this email directly, view it on GitHub
https://github.com/rust-lang/rust/issues/12111#issuecomment-222854362,
or mute the thread
https://github.com/notifications/unsubscribe/AFbiBuZLd4BEXQ_ukTRQBaNBopRYxGJeks5qHMingaJpZM4BgVOt
.

—
You are receiving this because you are subscribed to this thread.
Reply to this email directly,view it on GitHub(https://github.com/rust-lang/rust/issues/12111#issuecomment-222859084), ormute the thread(https://github.com/notifications/unsubscribe/AABsirpH9ngCZkLrCFkJ0_ZJUEIPpPCYks5qHM_MgaJpZM4BgVOt).

Alternatively allow operator overloading

You can already overload "+", "-" and "*" (and certainly "/").

I know this has been "decided" already, but this is disappointing. Case in point from code I have written this afternoon:

What I must (and did) write:

self.pool.set(self.alloc_count);
let result = self.alloc_count as u32;
self.alloc_count += 1;
Some(result)

What I wish I was able to write:

self.pool.set(self.alloc_count);
Some(self.alloc_count++ as u32)

So much extra logic, and statekeeping to avoid using a postincrement operator. :-1: I hope this community will reconsider.

There is nothing to reconsider. Personally, I think the ++ syntax is a huge mistake. Also, why not doing:

self.pool.set(self.alloc_count + 1);
Some(self.alloc_count as u32 - 1)

?

It's as long as your second code example.

Is this what you meant?

self.pool.set(self.alloc_count);
self.alloc_count += 1;
Some(self.alloc_count as u32 - 1)

I saw someone using an extension trait to implement post-increment.

trait PostInc {
    fn post_inc(&mut self) -> Self;
}
impl PostInc for usize {
    fn post_inc(&mut self) -> Self {
        let x = *self;
        *self -= 1;
        x
    }
}

self.pool.set(self.alloc_count);
Some(self.alloc_count.post_inc() as u32)

Macros can also be used.

macro_rules! post_inc {
    ($x:expr) => {{ let tmp = $x; $x += 1; tmp }}
}

self.pool.set(self.alloc_count);
Some(post_inc!(self.alloc_count) as u32)

But I'd like to avoid post-increment in any way and give more explanatory name to the temporary variable. let x = foo; something; x is an occasional pattern elsewhere as well.

@sinkuu This seems like a reasonable viable workaround to the issue. I'll play with this as a starting point to see if I can achieve what I am looking for (I will attempt to genericize this concept). Thank you for this!

Yes, the temp variable is very common in swap patterns and other similar behaviors and is immediately recognizable as idiomatic--if I can't have it built into the language, this + Rust's static polymorphism (monomorphization) is probably the next best thing. Thank you again.

It becomes even uglier when you need to combine it with wrapping integer operations. Consider for instance this getter for a primitive ringbuffer I am trying to prettify at the moment:

fn get(&mut self) -> Option<u8> {                   
  if self.head == self.tail { return None; }       
  self.tail = self.tail.wrapping_add(1);           
  Some(self.data[self.tail.wrapping_sub(1) & MASK])
}                                                  

This is much noisier than the equivalent C

int get(*buf b)
{
  if (b->head == b->tail) return -1;
  return b->data[b->tail++ & MASK];
}

I would've voted for a method called post_increment() on integer types. It's still shorter than doing { let y = x; x += 1; y }

I would've voted for a method called post_increment() on integer types. It's still shorter than doing { let y = x; x += 1; y }

But below example cannot run: @norcalli

fn main() {
    let mut x = 2134;
    // simulate: console.log(x, ++x);
    println!("{}, {}", x, {let y = x; x += 1; y} );
}

Playground

Was this page helpful?
0 / 5 - 0 ratings

Related issues

Leo1003 picture Leo1003  Â·  898Comments

GuillaumeGomez picture GuillaumeGomez  Â·  300Comments

nikomatsakis picture nikomatsakis  Â·  210Comments

nikomatsakis picture nikomatsakis  Â·  268Comments

nikomatsakis picture nikomatsakis  Â·  331Comments