There are some important semantic differences between increment and decrement operators vs the addition and subtraction assignment operators.
Consider an iterator walking some kind of data structure like an array vs an expensive generator function. It may not be possible to jump to the Nth element without computing the intermediate elements first.
So while:
iter += 3
is equivalent to:
iter.next().next().next()
and indeed you can construct the whole of arithmetic this way, it is not necessarily efficient.
Defining a additional assignment operator can be used to imply that there is a short cut.
In some languages it is useful to imply the computational cost but not defining additional assignment if it is not efficient.
So for a number type you can easily do:
x = 1;
x += 5; // what it looks like - just a simple addition operator
It would seem less intuitive to write:
class iterator
{
calculate_next();
opeator++() { calculate_next(); }
};
foo++ // fine as alias for calculate_next;
foo+=5 // less obvious as an alias for calculate_next repeated 5 times;
There is potentially a loop in the second case which does not exist in the first case. Though it gives the right answer, Peano arithmetic is not computationally efficient.
Another difference is that increment and decrement tend to be usable as expressions while addition assignment tends to useable only as a statement.
x+=2
is more intuitive than:
y=(x+=2)
If used as an expression it would also be a pre-increment whereas x++ is a post increment.
With increment and decrement operators (in C and C++ at least) you can define whether the value is incremented before or after the return.
That is in the context of:
y=++x;
++x
means:
x=x+1;
return x;
Whereas in the context of:
z=x++;
x++
means:
ret=x;
x=x+1;
return ret;
Thus:
y > z
All this is true even without considering the historical origins of increment and decrement in relation to C as a layer on top of assembly languages which may themselves have distinct increment and addition operations.