++ vs +=1

1,154 views
Skip to first unread message

Starfish

unread,
Feb 13, 2013, 7:25:29 AM2/13/13
to golan...@googlegroups.com
What is the rationale for the ++ and -- operators as syntactic sugar for +=1 and -=1 respectively?

Does this not introduce unnecessary choices and make it difficult to simplify statements such as:

a++
b++ 

Jan Mercl

unread,
Feb 13, 2013, 7:52:32 AM2/13/13
to Starfish, golang-nuts
On Wed, Feb 13, 2013 at 1:25 PM, Starfish <ahn...@rocketmail.com> wrote:
> What is the rationale for the ++ and -- operators as syntactic sugar for +=1
> and -=1 respectively?

I guess b/c `a++` is half the characters of `a += 1`

> Does this not introduce unnecessary choices and make it difficult to
> simplify statements such as:
>
> a++
> b++

Here you lost me. What simplification of `a++`, beyond the single CPU
instruction produced by many compilers, is to be expected?

-j

David Symonds

unread,
Feb 13, 2013, 7:59:15 AM2/13/13
to starfish, golang-nuts

ken likes ++.

Patrick Mylund Nielsen

unread,
Feb 13, 2013, 8:01:03 AM2/13/13
to Jan Mercl, Starfish, golang-nuts
> I guess b/c `a++` is half the characters of `a += 1`

Yes, but Go's philosophy is that it terseness isn't a goal--being clear is. I don't see why this exists either, but I don't feel very strongly about it.



--
You received this message because you are subscribed to the Google Groups "golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.



Jan Mercl

unread,
Feb 13, 2013, 8:04:22 AM2/13/13
to Patrick Mylund Nielsen, Starfish, golang-nuts
On Wed, Feb 13, 2013 at 2:01 PM, Patrick Mylund Nielsen
<pat...@patrickmylund.com> wrote:
>> I guess b/c `a++` is half the characters of `a += 1`
>
> Yes, but Go's philosophy is that it terseness isn't a goal--being clear is.
> I don't see why this exists either, but I don't feel very strongly about it.

Well, I think `i++` or `x--` _clearly_ communicates its semantics.

-j

Patrick Mylund Nielsen

unread,
Feb 13, 2013, 8:06:24 AM2/13/13
to Jan Mercl, Starfish, golang-nuts
I disagree. That "++" mutates wouldn't be intuitive to anyone who doesn't know a C-like language.

Robotic Artichoke

unread,
Feb 13, 2013, 8:26:35 AM2/13/13
to golan...@googlegroups.com
With it only being allowed as statements I don't see a real problem. I'll continue to use += 1 because I think it's more clear overall and easier to change to a different value if needed.

a++ as an expression and especially ++a as an expression tends to be confusing at times and I'm glad they removed that. Sometimes you would have to run something just to make sure what you think would happen actually happens.

Jan Mercl

unread,
Feb 13, 2013, 8:37:07 AM2/13/13
to Patrick Mylund Nielsen, Starfish, golang-nuts
On Wed, Feb 13, 2013 at 2:06 PM, Patrick Mylund Nielsen
<pat...@patrickmylund.com> wrote:
> I disagree. That "++" mutates wouldn't be intuitive to anyone who doesn't
> know a C-like language.

Why should non programmers read Go source code?

-j

Gustavo Niemeyer

unread,
Feb 13, 2013, 8:38:13 AM2/13/13
to Patrick Mylund Nielsen, Jan Mercl, Starfish, golang-nuts
On Wed, Feb 13, 2013 at 11:06 AM, Patrick Mylund Nielsen
<pat...@patrickmylund.com> wrote:
> I disagree. That "++" mutates wouldn't be intuitive to anyone who doesn't
> know a C-like language.

I could argue about the delta of intuitiveness of "+=" vs. "++" to
heat up that conversation, but really.. this is a done deal, and a
pretty insignificant one. Let's all go coding.


gustavo @ http://niemeyer.net

Patrick Mylund Nielsen

unread,
Feb 13, 2013, 8:42:29 AM2/13/13
to Jan Mercl, Starfish, golang-nuts
Python doesn't have ++ or --, and somehow it manages to be a programming language.

Patrick Mylund Nielsen

unread,
Feb 13, 2013, 8:46:02 AM2/13/13
to Gustavo Niemeyer, Jan Mercl, Starfish, golang-nuts
Completely agree. I responded because these knee-jerk responses that all the choices Go have made are perfect because <insert a fitting argument that contradicts a basic tenent of the language> are annoying. Starfish asked what the rationale was, not for the language to be changed.

So far the rationale seems to be that Ken likes ++. That's fine. Just don't try to sell it as something different.

chris dollin

unread,
Feb 13, 2013, 8:46:30 AM2/13/13
to Jan Mercl, golang-nuts
You don't have to be a non-programmer to not know a C-like
language: there are plenty of them out there, and sometimes
they are someone's first language.

Chris

Common Lisp, Scheme, Prolog, Standard ML, Pop11, Pascal,
Basic, Smalltalk ...

--
Chris "allusive" Dollin

Jan Mercl

unread,
Feb 13, 2013, 9:04:25 AM2/13/13
to chris dollin, golang-nuts
On Wed, Feb 13, 2013 at 2:46 PM, chris dollin <ehog....@googlemail.com> wrote:
> You don't have to be a non-programmer to not know a C-like
> language: there are plenty of them out there, and sometimes
> they are someone's first language.

Impossible, can't be true. Every _programmer_ must know C. Q.E.D.

-j

PS: Yeah, I deserve whatever comes next ;-)

Starfish

unread,
Feb 13, 2013, 10:05:53 AM2/13/13
to golan...@googlegroups.com, Starfish
> Does this not introduce unnecessary choices and make it difficult to 
> simplify statements such as:
>
> a++
> b++

Here you lost me. What simplification of `a++`, beyond the single CPU
instruction produced by many compilers, is to be expected?

-j
Yes, you're right. I was thinking it could be written 'a, b += 1, 1', but it can't of course.

Johann Höchtl

unread,
Feb 13, 2013, 11:42:51 AM2/13/13
to golan...@googlegroups.com


Am Mittwoch, 13. Februar 2013 14:26:35 UTC+1 schrieb Robotic Artichoke:
With it only being allowed as statements I don't see a real problem. I'll continue to use += 1 because I think it's more clear overall and easier to change to a different value if needed.
But it comes with some surprises: a *= 2 + 2 means a = a * (2 + 2)
 

minux

unread,
Feb 13, 2013, 12:10:26 PM2/13/13
to Johann Höchtl, golan...@googlegroups.com

On Thu, Feb 14, 2013 at 12:42 AM, Johann Höchtl <johann....@gmail.com> wrote:
Am Mittwoch, 13. Februar 2013 14:26:35 UTC+1 schrieb Robotic Artichoke:
With it only being allowed as statements I don't see a real problem. I'll continue to use += 1 because I think it's more clear overall and easier to change to a different value if needed.
But it comes with some surprises: a *= 2 + 2 means a = a * (2 + 2)
the rhs is treated as a group here (*= here is part of the assignment statement,
see http://golang.org/ref/spec#Assignments)
besides, i think making it expand to a = a * 2 + 2 will confuse a lot more.

Kevin Gillette

unread,
Feb 13, 2013, 1:08:17 PM2/13/13
to golan...@googlegroups.com
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.

Michael Jones

unread,
Feb 13, 2013, 2:38:33 PM2/13/13
to Kevin Gillette, golan...@googlegroups.com
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.
>
> --
> You received this message because you are subscribed to the Google Groups "golang-nuts" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts...@googlegroups.com.
> For more options, visit https://groups.google.com/groups/opt_out.
>
>



--
Michael T. Jones | Chief Technology Advocate  | m...@google.com |  +1 650-335-5765

Thomas Bushnell, BSG

unread,
Feb 13, 2013, 3:02:49 PM2/13/13
to Patrick Mylund Nielsen, Jan Mercl, Starfish, golang-nuts
If you don't think ++ mutates, what would you think it did?


Patrick Mylund Nielsen

unread,
Feb 13, 2013, 3:25:23 PM2/13/13
to Thomas Bushnell, BSG, Jan Mercl, Starfish, golang-nuts
n++ and n-- could just as well have been analogous to succ(n) and pred(n), i.e.

n := 3
on := n++
# n is 3
# on is 4

With n += 1, this is much clearer (and yes, n = n + 1 would be more straightforward still.)

Thomas Bushnell, BSG

unread,
Feb 13, 2013, 3:29:09 PM2/13/13
to Patrick Mylund Nielsen, Jan Mercl, Starfish, golang-nuts
Yes, but that isn't syntactically correct Go code.

Since "n++" is a statement, not an expression, I'm not sure what real confusion happens.

Patrick Mylund Nielsen

unread,
Feb 13, 2013, 3:42:24 PM2/13/13
to Thomas Bushnell, BSG, Jan Mercl, Starfish, golang-nuts
Alright, I'm going to give up now, but I leave you with this:

n is a value, not a reference. Why does "n++" mutate n if it doesn't re-assign, especially when you need to do s = append(s, x) to grow a slice, and a[i] = x rather than v = x to change a value in an array?

n += 1 / n = n + 1 are both clearer than n++. n++ makes sense because you know what it does from C, not because anything else in Go has conditioned you to find it intuitive. With less and less people actually starting out learning C, and more and more educational institutions using Go as an introductory language, you can't really say "++ is obvious, duh."

Thomas Bushnell, BSG

unread,
Feb 13, 2013, 3:44:41 PM2/13/13
to Patrick Mylund Nielsen, Jan Mercl, Starfish, golang-nuts
I agree completely that someone without C-like experience might be surprised that "i++" is mutating. However, what I'm saying is that there isn't any other plausible interpretation it could have either. So someone without C-like experience would go "hrm, I wonder what that does", which isn't so bad. They would not go "ah, this does X" when it actually does something else.

I'm not saying it's obvious or intuitive. I'm saying that someone without C experience would not be able to form any conclusion about it.

This is true precisely because it can only occur as a statement. If it could be used as an expression, then certainly it could cause confusion.

Patrick Mylund Nielsen

unread,
Feb 13, 2013, 3:48:29 PM2/13/13
to Thomas Bushnell, BSG, Jan Mercl, Starfish, golang-nuts
Yeah, granted. I'm glad that you can't abuse it in Go.

Peter

unread,
Feb 13, 2013, 4:16:47 PM2/13/13
to golan...@googlegroups.com, Kevin Gillette
Does the compiler optimise 

x % 64

into 

x & 63

?

(Then you wouldn't need the comments.)

Peter

unread,
Feb 13, 2013, 4:23:07 PM2/13/13
to golan...@googlegroups.com, Kevin Gillette
On checking the spec, no - since x is signed. http://golang.org/ref/spec#Arithmetic_operators

If the dividend is positive and the divisor is a constant power of 2, the division may be replaced by a right shift, and computing the remainder may be replaced by a bitwise "and" operation:

Rob Pike

unread,
Feb 13, 2013, 4:24:41 PM2/13/13
to Peter, golan...@googlegroups.com, Kevin Gillette
On Wed, Feb 13, 2013 at 1:16 PM, Peter <peter.a...@gmail.com> wrote:
> Does the compiler optimise
>
> x % 64
>
> into
>
> x & 63

I hope not, because that is incorrect if x is negative.

-rob

Michael Jones

unread,
Feb 13, 2013, 4:39:02 PM2/13/13
to Rob Pike, Peter, golan...@googlegroups.com, Kevin Gillette
No, for the reason Rob states. My values are all >0, so it works for me, but doing all the casts is just too ugly and having the parameter be of type uint64 pushes the cast-contamination issue to the callers...

--
You received this message because you are subscribed to the Google Groups "golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.


peterGo

unread,
Feb 14, 2013, 5:31:41 PM2/14/13
to golan...@googlegroups.com, Kevin Gillette
Michael,

"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? . . . This is certainly not likely."

Yes. Using IBM mainframe Assembler machine language SS instructions,

    ZAP   a,b
    AP     a,c

IBM z/Architecture Reference Summary, Eighth Edition (September, 2012), SA22-7871-07.

Peter

Michael Jones

unread,
Feb 14, 2013, 5:36:59 PM2/14/13
to peterGo, Kevin Gillette, golang-nuts

Ha! I knew there would a counter example. Thanks! The DEC VAX could too... and arguably the TI CPUs.

Reply all
Reply to author
Forward
0 new messages