38

I was fiddling around with different things, like this

var a = 1, b = 2;
alert(a + - + - + - + - + - + - + - + b); //alerts -1

and I could remove the spaces, and it would still work.

a+-+-+-+-+-+-+-+b

Then I tried

a + + b

It ran and evaluated to 3, but when I removed the spaces, (a++b) it wouldn't run, and it had a warning which read "Confusing plusses."

I can understand that in cases like

a+++++b

which could be interpreted as any of the following

(a++) + (++b)
(a++) + +(+b)
a + +(+(++b))
a + +(+(+(+b)))

that it would be confusing.

But in the case of

a++b

the only valid way to interpret this, as far as I can tell, is

a + +b

Why doesn't a++b work?

p.campbell
  • 98,673
  • 67
  • 256
  • 322
Peter Olson
  • 139,199
  • 49
  • 202
  • 242

7 Answers7

58

The Javascript parser is greedy (it matches the longest valid operator each time), so it gets the ++ operator from a++b, making:

(a++) b

which is invalid. When you put in spaces a + + b, the parser interprets it like this:

(a) + (+b)

which is valid and works out to be three.

See this Wikipedia article on Maximal munch for more details.

Digital Plane
  • 37,354
  • 7
  • 57
  • 59
  • 7
    I think this is the key answer: parser is **greedy**. – Andrey Sep 20 '11 at 21:25
  • 3
    If it wasn't greedy, it would be pretty useless. 'a++' would be interpreted as 'a + +', which is illegal. One of the important insights is that figuring out which tokens the input consists of comes before figuring out what those tokens mean. So '++' is going to be the '++' token even if that token is not valid in that context. – David Schwartz Sep 21 '11 at 03:13
12

It's reading a++, then it encounters a b and doesn't know what to do with it.

Niet the Dark Absol
  • 320,036
  • 81
  • 464
  • 592
7

This is b/c of the difference in unary operators.

"a + + b" is the same as "a + (+b)"
"a++b"    is the same as "(a++) _ b"  <--- there is a missing operator where the _ is
mlathe
  • 2,375
  • 1
  • 23
  • 42
3

Javascript's operator precendence rules for the ++ increment operator has no left-right associativitity. That means a++b can be interpreted as a++ b or a ++b depending on the particular implementation. Either way, it's a syntax error, as you've got 2 variables, one unary-operator, and nothing joining the two variables.

In practical terms:

a = 1
b = 2;

a++ b; -> 2 2
a ++b; -> 1 3

What does 1 3 mean as JS code?

Marc B
  • 356,200
  • 43
  • 426
  • 500
3

Most programming language parsers tries to get longest chunk of text that make sense, so when Javascript sees:

[a][][][][]

"variable a" - it make sense, let's see next character:

[a][+][][]

"will be adding to varaible a" - it make sense, let's see next character:

[a][+][+][]

"will post-increment variable a" - it make sense, let's see next character,

[a][+][+][b]

This does not make sense. I have two expressions (a++) and (b) and no infix operator between them.

If you make it a+ +b it will not find the ++ operator and it will work as a + + b.

Peter Olson
  • 139,199
  • 49
  • 202
  • 242
Michał Šrajer
  • 30,364
  • 7
  • 62
  • 85
1

Longest Match rule comes into picture here. It says parser has to take longest token into consideration starting from left to right (I assume Javascript's grammar is Left to Right). So just apply this rule and you will get your answer.

Parser will start from left and will make a, +, + & b separate tokens in case of "a + + b" (due to white space in between them). In case of "a++b" it will apply longest match rule and will create a++ & b as token. a++ b as an expression does not make any semantic sense hence it will not be compiled.

Vineet G
  • 175
  • 1
  • 1
  • 8
0

The answer is that ++ is an operator as well as +, and that + + is two + operators, not a ++ operator.

Although it's not Javascript, C++ has similar fun with + and ++ operators. This was investigated in one of the Gurus of the Week from way back when.

Kaz Dragon
  • 6,681
  • 2
  • 36
  • 45