Thursday, March 12, 2009

JavaScript needs Elvis

I submitted an enhancement request to the Mozilla folks yesterday. My request? Add an Elvis operator to JavaScript.

If you program in Groovy, you already know what I'm talking about, and it has nothing to do with impersonators or Las Vegas.

If you're not familiar with the Elvis operator, here's the text of my enhancement request to Mozilla:

An Elvis operator similar to Groovy's (which is also being considered forScala, and is in the vein of C#'s null-coalescence operator) would addsignificant value to JavaScript by letting coders write safer scripts with verylittle added effort.

To which I say: Yes, of course, that sort of kludgy thing works and people use it all the time. But is it right?

While I can appreciate Eich not wanting to "junk up" JavaScript with new operators, I think using the logical-OR operator in the foregoing hacky way does nothing to make code more readable or preserve ||'s original semantics, IMHO. That's the whole point of having a separate operator. The semantics are unambiguous (to a human being, which is what counts; never mind the interpreter).

I respect Brendan Eich more than apple pie itself, but I think it's significant that others have already considered his argument and found it wanting.

There's still much to recommend Elvis. Java could certainly benefit from it. How many lines of sanity-checking code have people written at the start of a method to to see if arguments are null? More important: How many lines of such code have not been written (through sheer oversight), resulting in mayhem later? (Let he who is without sin throw the first NullPointerException.)

While we're at it, I think Java could use a safe property accessor (a la Groovy):theName = user?.name; // gives null, not NPE, if name is null

Colebourne has published data (acquired at Devoxx) showing that better null handling is the No. 1 most requested feature by Java programmers. The actual whiteboard photo from the data-gathering session is here (warning: large image).

When programmers beg for a simple syntax feature that makes the language safer and easier to read (while eliminating tedious sanity-checking boilerplate), why not put the feature into the language? What justification could there be for not doing so? Who benefits by keeping a feature out of the language that would cut down on null pointer exceptions?

Does JavaScript (and Java) need Elvis? I'm convinced it does. What do you think?

5 comments:

Part of the reason I prefer using || is that it's not a logical-OR operator in my mind. It's a shortcut-boolean-OR. In other words, it keeps evaluating operands until one is not falsy. My impression has been that this was the original meaning of this operator from the beginning, but the documentation never reflected this (since it was written by Java / C devs?).

There's a similar argument for the shortcut-boolean-AND operator, too.

@unscriptable: C and Java have short-circuiting || and && -- C always has, so all C-derived languages that I know of do to.

The statement "... I think using the logical-OR operator in the foregoing hacky way does nothing to make code more readable or preserve ||'s original semantics" shows a lack of familiarity with not only short-circuiting in the original semantics of JS, but more to the point, of the value-preserving nature, inspired by Perl and various Lisp dialects of JS || and &&.

In JS, e1 || e2 not only evaluates only e1 if it is truthy -- the result is the value of e1, not true. If e1 is falsy, then the result is the value of e2, not the result of converting e2 to a boolean value. Similarly for &&.

This was standardized 12 years ago in ECMA-262 (ES1). It is used idiomatically all over the web, which is why I argue (not dismissively, or I would not have written a comment in that bug) that it is fruitless to add another operator -- so long as the looseness of JS's truthy and falsy judgments is considered good.

If we need a more precise test than "converts to true" or "converts to false" to decide short-circuiting (but not of course result value), then there could be room for a ?? or ?: operator.

If you read the es-discuss@mozilla.org list archives, you will find multiple threads on this question, citing C#'s ?? operator and Ruby's || and ||= operators (Ruby || is similar to JS || but not the same). For ES4 we considered ||= and &&=, decided the latter was useless, but kept the former as short-hand for the very common JS idiom:

function foo(bar) { bar = bar || default; ... }

Arguing about other languages, which may or may not have JS's || and && Perl-inspired value preserving semantics, is not productive. Arguing about hackyness is flame-bait. JS has its own idioms, as does any language. Trying to crowbar another operator in because Groovy (or brand-X) does it won't work.

that asks for a new operator to be added to Mozilla's SpiderMonkey JS engine is, as I said in my comment #1 in that bug, barking up the wrong tree.

We extend JS from the last ECMA-262 standard in Mozilla's implementations, but we always try to do so based on public proposals that have been aired on es-discuss@mozilla.org, specified informally in the http://wiki.ecmascript.org/ wiki, and thus made known to Ecma TC39 members.

I suggest catching up on the ||= threads in es-discuss, then posting there, if you are interested in pushing ?: or anything like it. But again I don't think the case for ?: is grounded in the particular semantics of JS, or knowledge of what has come before "Elvis". It needs to be.