8

So I was fooling around with the new exponentiation operator and I discovered you cannot put a unary operator immediately before the base number.

let result = -2 ** 2; // syntax error
let result = -(2 ** 2); // -4
let x = 3;
let result = --x ** 2; // 4

From the documentation on MDN:

In JavaScript, it is impossible to write an ambiguous exponentiation expression, i.e. you cannot put a unary operator (+/-/~/!/delete/void/typeof) immediately before the base number.

In most languages like PHP and Python and others that have an exponentiation operator (typically ^ or **), the exponentiation operator is defined to have a higher precedence than unary operators such as unary + and unary -, but there are a few exceptions. For example, in Bash the ** operator is defined to have a lower precedence than unary operators.

I understand this was made an error by design. I don't understand this design decision. Who's really going to be surprised that -x ** 2 is negative? This follows not only other mainstream programming languages but a mathematical notation that has been in common use for hundreds of years and is taught to every high school algebra student.

In Javascript '1'+ 2 is '12' and '1'-2 is -1 but -1**2 raises an error because it could be ambiguous? Help me understand this design decision.

Community
  • 1
  • 1
kemotoe
  • 1,730
  • 13
  • 27
  • 1
    Writing `-x ** 2` instead of `- x**2` would make it ambiguous alone. – Bergi Nov 02 '17 at 06:41
  • Well, I believe I was always taught at school that -x raised to the power of y produces a positive number. So, -1**2 should produce 1. At least this is what I believe was taught, and I am sufficiently confident that my belief is correct. – doubleOrt Dec 09 '17 at 16:55
  • 1
    Why the heck was this question downvoted ? – doubleOrt Dec 09 '17 at 17:25
  • 1
    @doubleOrt - Agreed, very strange (about the vote). BTW, in math, `-1²` is `-1`. It's `-(1²)`, not `(-1)²`. I went 'round and 'round in my head on that one and finally [punted and asked the question](https://math.stackexchange.com/q/3027197/165692). It's been **that** long since math class. But I'm also a bit embarrassed to have asked, since I routinely see things like `-2³² + 1` and have no trouble interpreting that correctly (2³² = 4294967296, -4294967296 + 1 is -4294967295). – T.J. Crowder Dec 05 '18 at 15:54
  • @T.J._Crowder I am actually quite ashamed of my comment now that I read it, -1**2 only takes a basic understanding of operator precedence in Math, and "(-x)" raised to the power of "y" does not always produce a positive. – doubleOrt Dec 06 '18 at 13:43
  • The question is "lame" -- in that one can make arguments in either direction to support ones desired outcome. Ex: find a calculator with a exponent or squaring function. Type in -2 and square it. or raise it to '2'. I think you would be hard pressed to find one that came up with -4 as an answer. Negative numbers were around long before "operators", let alone "unary ones". Yet from a practical point of view, why would same calculator allow -2**1 and -2**2, but not -2**1.5. See, you can justify it either way! "Lame"... – Astara May 09 '21 at 15:05

1 Answers1

12

I don't understand this design decision.

Read more about it at https://esdiscuss.org/topic/exponentiation-operator-precedence, https://esdiscuss.org/topic/power-operator-why-does-2-3-throws, https://github.com/rwaldron/tc39-notes/blob/master/es7/2015-09/sept-23.md#exponentiation-operator and https://github.com/rwaldron/tc39-notes/blob/master/es7/2015-09/sept-24.md#exponentiation-operator.

Who's really going to be surprised that -x ** 2 is negative?

Enough people to matter. Some relevant quotes from the above resources:

  • "making ** bind tighter than unary operators would break x**-2. And making it sometimes tighter and sometimes looser would be too confusing and lead to other opportunities for precedence inversion." - Waldemar Horwat
  • "Given the conflict between the history of ** in other languages, [and] the general pattern that unary binds tighter than binary, any solution at this point will confuse many people." - Mark S. Miller
  • "acknowledge the prospect of significant whitespace: -x**2 === -(x ** 2) and -x ** 2 === (-x) ** 2" - Alexander Jones
  • "The problem is, however rare unary minus before an exponentiation expression may be, the lack of superscript-with-smaller-font sugests that - binds tighter than **. And indeed apart from dot (a special form whose right operand must be a lexical identifier-name) and square brackets (which isn't an infix operator per se), unary operators bind tighter than binary in JS as in C and other C-derived languages." - Brendan Eich
  • "For math it seems obvious that -52. But for -5 ** 2, because of the whitespace around the infix operator. Even without space, - seems to be part of the literal." - Dave Herman
  • [Regarding programming language precedence], "effectively zero people have an intutition about this from other languages. Agree people have an itutition that ** is the exponentiation operator. But people usually try to avoid dark corners so they never develop an intuition for negative bases." - Dave Herman

In Javascript '1'+ 2 is '12' and '1'-2 is -1 but -1**2 raises an error because it could be ambiguous?

Well they put considerably more effort in the design of extensions to the language today :-) It's the best solution that they could reach consensus for.

Bergi
  • 630,263
  • 148
  • 957
  • 1,375