Increment operator in Rust

Why rust havent incement operator? If assembler haves incement instruction then best programmer language must have this operator? Where I not right?

1 Like

Doesn’t really matter on modern platforms, but would be nice anyway

1 Like

If I answer my question it's "just because" :smiley:

It isn’t necessary, i’d say. On modern x86 inc and dec are pretty much the same as add 1 and sub 1 in terms of performance. You can write macros and use core::arch::asm inside if you want, of course

1 Like

There's no need for any modern programming language to have operators that directly represent machine instructions. It's the compiler's job to generate good machine code, not the programmer's. For example, on x86/64 LLVM may translate a += 1 to either inc or add 1 depending on the situation, and it does know better than the programmer.

28 Likes

I cannot agree with you. I’m not “a true pro”, but modern programmers are forgetting what programming really is. IMHO it’s very important to control what’s going on under the hood, and that’s why I chose Rust.

I’ve never seen LLVM generating inc and dec :face_with_monocle:

U think write 3 char better 2?
P.S. I know how this work in LLVM, but I dont know why RUST havent this simple operator ++

I think the main reason is that the C-type ++ with its prefix and suffix forms is often confusing. Even though in Rust, a hypothetica inc/dec operator would likely only have a suffix form and return (), there's also the question of what to do with overloading, should it be syntactic sugar for += 1 or its own implementable trait, and anyway, no matter how small the feature, it adds complexity to the compiler, and in Rust it was deemed that the benefits don't outweigh the costs. Saving a single character is IMO not worth it, especially given that in Rust, index- or pointer-based loops are much, much rarer than in C. In general, programming languages should make common things easy to write and rarer things more descriptive if longer.

18 Likes

Here is an example of Rust code being compiled into assembly inc:

7 Likes

Interesting previous discussion on this same topic:

2 Likes

Post-increment and pre-increment operators only save a microscopic bit of typing. When used in expressions of any complexity, those operators are an infuriatiing source of subtle bugs.

I don't see any reason for Rust to implement them at all, and I see some good reasons not to.

10 Likes

Because the compiler is smart enough that x = x + 1; can be turned into INC in assembly without needing an operator for it.

What you type in the source language -- including in C++! -- has very little relationship to the assembly to get in the end. Notably, you often don't even get INC, but LEA, because that doesn't affect flags.

If your top priority is to write the fewest characters in the source code, I suspect that Rust will not be to your taste. There are many places where Rust intentionally requires that the programmer write more than is strictly required, in order to get better error messages, for better semver, etc.

If you want to type less, can I interest you in https://en.wikipedia.org/wiki/Code_golf#Dedicated_golfing_languages?

INC is niche in that it affects all the flags except CF.

In general, LLVM will prefer using LEA to not affect flags and to leave the math ALUs available for math, using the address calculation units instead.

I suspect that if you do something like x -= 1; if x != 0 you'd be more likely to see a DEC.

12 Likes

This is a terrible goal in any language, not just Rust. I once worked with a C# programmer who would constantly abuse inheritance, just to save a few lines of duplicate code for classes that had very little in common.

3 Likes

Well, let me ask the converse – do you think saving a single character in source code is an improvement worth extending the language for? Hardly.

1 Like

Ok, im death, I know too small to argue with you

Indeed! This uses lea:

pub fn increment1(mut a: u32) -> u32 {
    a -= 1;
    a
}

This uses dec:

pub fn increment2(mut a: u32) -> u32 {
    a -= 1;
    if (a == 0) { 7 } else { a }
}

Apparently inc / dec is sometimes less efficient because partially updating the flags register can create additional dependencies for subsequent instructions.

11 Likes

Not all processors, hence not all assemblers, have increment/decrement instructions.

Personally I think the post increment/decrement as you see in C/C++ can be confusing and I have seen it lead to bugs.

At best they save a character or two of typing. Hardly worth worrying about. I don't think we should be striving to write the shortest most cryptic code we can dream up.

Rust, being a better programming language, does not include these redundant and confusing operators.

5 Likes

Drive-by note that iterators being idiomatic avoids what would be a lot of incrementing loops in other languages.

4 Likes

The equivalent C++ code generates exactly the same output with Clang, as well.

If you start looking at different C++ compilers, it gets murkier; despite using pre-decrement --a in both cases, GCC and MSVC (with __fastcall) use LEA in the first case, but SUB in the second, so the C++ decrement operator doesn’t compile to DEC at all.

3 Likes

The notation is irrelevant to what machine instructions get selected. The first thing a C++ compiler will do when processing --a and a = a - 1 is to convert both into the same representation in its intermediate language, long before it gets to generating machine code for a particular machine.

4 Likes