Skip to content

Instantly share code, notes, and snippets.

@csnover
Last active August 29, 2015 14:04
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save csnover/6210bc20379476d18e1a to your computer and use it in GitHub Desktop.
Save csnover/6210bc20379476d18e1a to your computer and use it in GitHub Desktop.
Hey snover, do you really have such a big problem with adding an exponentiation operator?

No, I don’t, not really. For projects that do these operations a lot, it would probably be a very useful enhancement. My reaction is a manifestation of my larger frustration with the direction of EcmaScript and TC39.

Why do I feel this way? A few reasons.

One, because here is the trap that we’re stuck in now:

  • Someone decides that feature X isn’t good enough, even though it has worked fine for years, so proposes functionally identical feature Y instead (see: exponentiation operator)
  • TC39 has decreed that EcmaScript shall not be versioned, so “legacy” syntax X cannot ever be removed
  • Now we have two competing ways to do the same thing
    • But sometimes the two ways are slightly different (reduced fat arrow function syntax, DIFFERENT lexical scope behaviour)
    • And sometimes the new features force people to opt-in to unrelated features (class keyword FORCES strict mode for all code inside the class)
    • Also, nobody can actually use the new feature without a compiler like Traceur because they still have to support old-ES environments

Two, because every time I hear someone talking about how great their bit of sugar for ES.next is while I still literally can not do things like NOT CRASH in low-memory conditions with EcmaScript, with no solution on the horizon, it is upsetting. It feels like people involved with the direction of the specification are utterly tuned out from reality[*]. Cognitively, I know not everyone can be focused on fixing all the big problems all of the time, but it seems like a disproportionate amount of focus is put on bikeshedding trivial enhancements (fat arrow! symbols! comprehensions! Promise.race!), and based on my own experience I suspect that these little squabbles sap all the energy necessary to address the more serious problems with EcmaScript (and the ES6 spec):

  • Can’t manage memory (pause/resume GC for timing-sensitive programs, data caches that can be flushed in low-memory conditions, etc.)
  • Date time string format still does not actually conform to ISO-8601
  • Regular expressions still do not have Unicode categories (\p{L})
  • Still single-threaded well into the era of multi-core processors
  • No guaranteed secure RNG suitable for cryptography
  • No standard for handling uncaught global exceptions
  • Retrieving a property descriptor for the same property always creates a new object
  • Promises are hacks for a missing async syntax
  • ES6 Module section still incomplete!
  • ES6 Proxy object section still incomplete!
  • ASI still dumb, still exists

Some people might argue that some of these things should be addressed by host objects, but they are issues common to all EcmaScript environments, so really should be in the EcmaScript standard (like Promises, that were originally going to end up as part of a DOM spec until they got put into EcmaScript 6 because they are so common).

Three, because the EcmaScript specification process was supposed to be evolutionary, not revolutionary. We’ve needed native modules to solve the CommonJS vs AMD splintering for years. We’ve needed Unicode support above the BMP for years. We’ve needed things like WeakMap for years. The EcmaScript/Web ecosystem would be in a much better place if someone had said “we’ll do symbols later”, or “let’s table these syntactic sugar arguments for now in order to publish solutions for the impossible things” and ES6 was published three years ago. Instead, we’re getting things like an extremely stripped-down class syntax, fat arrows, and more information hiding functionality while high-value features like Object.observe get bumped. It’s been six years since the Harmony process started. It’s going to be at least another year until ES6 is actually finalised, and then probably close to another decade until we can actually use these features without compiling down. To me, it’s a massively disappointing failure.

Finally, speaking directly to the exponentiation proposal, as requested by someone: The currently defined rationales for this proposal are not valid as written. That something exists in another field does not mean it is a good idea (appeal to popularity), and “niceness” is a subjective measurement. Mostly though, the implication in the blog that it helps make the feature easier to learn, and this is a problematic implication; adding this syntax may make this one feature easier to learn, but it makes all related parts of the language harder, and that’s a huge problem for an ecosystem that is already full of traps and legacy garbage.

With an exponentiation operator, new users must memorise a new operator precedence. Maybe this is not an issue for people that went to a good school and learned their BEDMAS/PEMDAS/BOMDAS, but the fact of the matter is that there are already 20 operator precedences in EcmaScript and people get them wrong quite often (like the precedence order of ! and in). Making the language easier to learn and use in general means reducing the number of facts that must be remembered in order to be proficient. Function calls are extremely common, so it’s mandatory to learn them, it’s not hard to know how they work, and they work the same everywhere.

Unfortunately, operator precedence is not the only thing that this proposal adds to the knowledge burden. Due to the realities of the real world, instead of one decent choice for users (Use Math.pow), this proposal makes many:

  1. Use ** and ignore non-ES7 environments
  2. Use ** and then learn how to use a compiler like Traceur and then compile your code back to ES6-
  3. Use Math.pow

Since the features are all identical, there is no real benefit for new users. There may be some benefit for more experienced users, but then any benefit of “learnability” is not applicable. (And in fact, due to the search engine non-discoverability of the string “**”, it may actually be less “learnable”, depending on how you are learning.)

Some concrete evidence to this point on syntax is what happens with the relaxed ES5 object trailing comma. New authors test their code in Chrome and everything works. Then they go to run their code in IE8 (because this is the real world—their company requires them to write code that works in IE8), and it blows up. Because that older browser doesn’t support that syntax and your newbie doesn’t have the 10 years of experience you do to figure out their mistake, they are confused, and end up needing to seek help.


In conclusion, my concerns about the proposal itself are honestly not that big. If it helps people feel better to type **, I don’t really care that much. It’s probably reasonable enough. My real concerns lie in the thought process that lead to this proposal, from a TC39 member, while ES6 is still not done, and the precedent that it’s OK to add “nice” syntax enhancements as long as people don’t object.

Of all the features that can be added to a language, new syntax introduces guaranteed backwards incompatibility and carries a greater risk of causing harm than other enhancements because it can’t be deprecated without breaking source code parsing. When the true underlying desire for a syntax change proposal seems to be to play “code golf” (i.e. to reduce the number of keystrokes), I will usually have a problem with it.

In many cases, introducing excessively terse syntaxes leads to less readable, less scannable, harder-to-maintain code. (Perl was famous for this; Ruby has a similar problem.) Average development teams are bad enough at creating well-structured, maintainable code; language authors should be eager to accept some reduced writing-efficiency (i.e. more keystrokes) in order to enforce certain patterns that make it easier to read and review later, and that make mastering the language less difficult. Many of the features in ES6 do not follow this pattern, and even if I and my team agree to refrain from using certain features, that won’t stop anyone else from using them in code that we have to interact with.

Also, given the size of EcmaScript at this point (669 pages), I’m feeling leery of putting more in it. The ES5 spec was pretty easy to read and pick things out of; the ES6 spec is not. The only language standard I could find bigger than EcmaScript 6 was the C++11 spec at around 1300 pages. The next closest is the C# spec at around 500 pages. Dart isn’t even 200 pages long. Go is even shorter.

With regard to the process issues I talked about, obviously we cannot go back in time and fix whatever led to there not being a new version of EcmaScript since 2009. But looking forward, once this round is done, I honestly feel like there are probably only two reasonable approaches for EcmaScript at this point:

  1. Stop adding syntactic sugar to the core language, standardise a high-performance low-level instruction set (like asm.js), and tell people to compile to this instruction set from other languages with whatever sugar they want (TypeScript, CoffeeScript, haxe, Traceur, whatever); or
  2. Add versioning to the language in a way that allows us to gracefully address forward-compatibility problems, and that allows the bad parts to actually be fixed and eventually purged from the universe.

I don’t really expect either of these to happen, but at least now I’ve said what my position is so I can go back to getting stuff done. :)

The end!

[*] Trying to head off any “If you don’t like the job the committee is doing then why don’t you try to join the committee?” comments here: I don’t have time for that, my company wouldn’t pay for me to do that, and I don’t want to spend my life arguing about things. I want to create products that make the world better while I can. I’ve stuck my head out to object to things in ES6 at least twice, and both times I was dismissed as having an irrelevant opinion. So, I’ll just keep making good stuff, and hopefully some people find it useful, and hopefully I don’t have to completely switch languages.

@mathiasbynens
Copy link

Add versioning to the language in a way that allows us to gracefully address forward-compatibility problems

Is that even possible?

[…] and that allows the bad parts to actually be fixed and eventually purged from the universe.

Same here.

@csnover
Copy link
Author

csnover commented Aug 6, 2014

Add versioning to the language in a way that allows us to gracefully address forward-compatibility problems

Is that even possible?

Maybe! Probably! It just depends on making it not so burdensome to everyone as to become unrealistic.

Now that EcmaScript will have fucking modules already (!), if they’re done right, there should be a boatload of stuff that can be safely done by importing new functionality as it becomes available from smaller specs (like Python PEPs), instead of writing these huge monolithic specifications that take forever and annoy everybody. The key for most things is to implement generic language features (annotations, proxies, operator overloads, object & property descriptor reflection, etc.) that add a lot of flexibility without requiring new syntax, though as long as the basic module format is designed to be forward-compatible, there could be some options for introducing new syntax too with fallbacks:

  • Multi-version module bundles
  • Inline pragmas (think @cc_on) that allow a parser to bypass blocks of code that it doesn’t understand to avoid syntax errors (kind of the same thing as the first one, but more granular)
  • (for browsers) HTTP requests with engine information in the header (so we don’t have to guess by User-Agent) for Vary content responses

If it is distilled down to a developer user-experience issue, at minimum, inserting a pragma that states the engine required for a code module, then loading that code module into an engine that did not support that version, would report an error that the environment was too old and halt parsing, instead of ignoring the pragma and then crashing on an “invalid” line of syntax or missing expected feature. Training users from the start to define which version of EcmaScript they want to use, and being told “this engine is older than that”, is a lot easier than having them run into random crashes—and, again, this allows a convenient mechanism for actually fixing bad APIs since the user is explicitly opting to work with the newer revision.

Anyway, I’m sure other people have had more time to think about it than I have. It’s a surmountable problem.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment