The axiomatic development of number systems, "natural numbers" and integers in particular, depends on the idea of a successor for each number. This means that many people will have a natural understanding of the concept.
Integral types in the C-family have n++ as the "become the successor" function for n, and n-- as the "become the predecessor" for n. Pascal and Ada have SUCC(n) for the successor and PRED(n) for the predecessor (which is n+1 and n-1 respectively, but is more sophisticated in Ada and Pascal when advancing through enumerant values.) When I see ++ I always read "next" and likewise "previous" or "prior" for --. It made sense to me from day one of C.
The operator_equal functions in C are more natural than the plain equal to one who has studied, designed, or built computers, as well as one who programs actual computers rather than the virtualized conception of computers suggested by high-level languages.
If a, b, and c are in memory, is there a computer in use today that can compute a=b+c where the operands come from memory and the result goes to memory? Is there one that can compute b+c where the operands come from memory and the result goes to a register? This is certainly not likely. Instead, actual computers can do either of the following:
r0 = load b
r1 = load c
r2 = r0 + r1 // aka, r2 = r0 + r1
a = store r2
or
r0 = load b
r1 = load c
r0 = r0 + r1 // aka, r0 += r1
a = store r0
If you've dealt with this, and learned to do the second "+=" version wherever possible to accomplish more with a limited supply of registers, then the idea of "+=" in a high-level language a pleasing window into the soul of the machine. In olden times, there was one register, the accumulator, and all the operations were of the operator_equals variety. In modern times, there are many registers, and fancy compilers do everything they can to save registers in just this way.
It is also a practical aid to comprehension. Just this morning I wrote this:
func (p *Plan) ClearZero(length, sum, residue int) {
index := (length*(p.sum+1)+sum)*p.words + (residue >> 6) // residue/64
mask := uint64(1) << uint(residue&0x3f) // residue%64
p.zero[index] &^= mask // tuple known to be zero
}
Personally, I like find it simpler as written than would be:
p.zero[index] = p.zero[index] &^ mask
Because (a) it's telling me that the left hand side value is being updated in place so I don't have to look closely to see that the two array indices are the same, it's shouting to the compiler to use the same address for the load and store. It's also the "half of the compiler's optimizations are in the developer's source code" mindset that several on the Go team believe. Imagine the ugly and expanded case:
p.zero[(length*(p.sum+1)+sum)*p.words + (residue >> 6)] = p.zero[(length*(p.sum+1)+sum)*p.words + (residue >> 6)] &^ uint64(1) << uint(residue&0x3f)
There are many cases where a compiler gets this as input. It has to deduce that the LHS index and the RHS indices are common expressions, that the slices are the same, and so that the same address can be used for bounds check, load, and store, that only one bounds check is needed, and so on. Optimizing compilers do this, but imperfectly at times and slowly as well. The "+=" style helps hugely here because all the things that need to be understood are as clear for the compiler as they are for the programmer.
One of my favorite things about C, perhaps my favorite thing, is that it embraces the true nature of computers. My least favorite thing about it is the other side of this same truth--it embraces and exposes a tiny subset of the true nature of computers (the "greatest hits" say) and leaves the rest out. This makes programs less efficient than they could be and worst, discourages CPU designers from extending computers in ways they otherwise might.
On Wed, Feb 13, 2013 at 10:08 AM, Kevin Gillette <
extempor...@gmail.com> wrote:
> A great many languages have increment/decrement operators, many with c++ semantics (it's an expression, prefixed use allowed). Javascript it's one example of this, and since js has a monopoly on browser-based programming, anyone wanting programmatic access to that medium will eventually notice ”++” anyway. Go compilers will quickly and thoroughly teach the semantic difference.
>
> Anyway, I've encountered many languages which don't have += style constructs, or c-style character escaping in strings, or even any concept of mutable variables. go was, not surprisingly, designed to not be particularly surprising to c programmers, and it's not possible to be unsurprising to everyone. C is arguably the dominant reference language for the ”imperative” programming paradigm, and it's semantics are (at least indirectly) well known to a great many programmers -- since go follows the same overarching paradigm, it's reasonable the language family's greatest common denominator is used as the conceptual base for its core imperative syntax.
>