Whether keywords should be allowed as names in function declarations

# David-Sarah Hopwood (17 years ago)

Brendan Eich wrote:

On Jan 20, 2009, at 11:06 AM, David-Sarah Hopwood wrote:

I don't see any relevant arguments in followups that would contradict the position above.

You replied selectively -- not nice.

Given that my position was that the case of "match[ing] an interface across a language bridge" was not plausible in the case of function declarations, I didn't think that the rest of the paragraph was relevant enough to quote. No other examples of cases in which it would be useful for a function name to be a keyword were given.

In such a case you could certainly use an object initialiser or assignment (doesn't matter which), but you couldn't give the function the intrinsic name 'delete'. Named functions have their uses, not so much for recursive calls as for better diagnostics and less inscrutable pretty-printing results.

Reporting a name that cannot be used to reference the function in most contexts, is arguably more inscrutable than requiring the programmer to change it to something that can be directly referenced.

Allowing keywords as function names makes for worse diagnostics in cases where the use of a keyword was unintentional. Consider

function delete(foo) { ... } ... delete(bar);

Here the programmer has forgotten that 'delete' is a keyword. If keywords are not allowed as declared names, then this mistake can be reported at the function declaration. If they are allowed, then the mistake cannot be reported (because "delete(bar)" is valid syntax), and will cause unintended behaviour.

'delete' in this example could also be 'if' (as also pointed out by MarkM), 'new', 'this', 'throw', 'typeof', 'while', and probably 'yield' in a future ES version.

For other keywords, an error might be reported at the point of use (if that statement is executed), but that is a less useful place to report it, and the error message may be less clear.

(I'm aware that implementations that support such names as an extension will not report the mistake in any case. I don't think that is a good enough reason to standardize this behaviour.)

It costs next to nothing for implementations or the spec to allow ordinarily reserved keywords to be used after 'function', and it benefits some users who already make use of this ability in JS1.7 and up. The low cost and utilitarian benefit is the basis for standardization.

The costs are:

  • preventing implementations from reporting errors when a keyword is used unintentionally. This is a significant cost, especially for new programmers who may not be entirely familiar with the full keyword set.

  • programs that rely on this change will fail to work on some ES3 implementations, when renaming the function would have been sufficient to allow them to work (if there is no other reliance on ES3.1).

# David-Sarah Hopwood (17 years ago)

David-Sarah Hopwood wrote:

Allowing keywords as function names makes for worse diagnostics in cases where the use of a keyword was unintentional. Consider

function delete(foo) { ... } ... delete(bar);

[...]

'delete' in this example could also be 'if' (as also pointed out by MarkM), 'new', 'this', 'throw', 'typeof', 'while', and probably 'yield' in a future ES version.

Also 'void' and 'return', and some identifiers that are technically not keywords but which I think have been proposed to be disallowed as function names, such as 'arguments' and 'eval'.

# Brendan Eich (17 years ago)

On Jan 20, 2009, at 2:09 PM, David-Sarah Hopwood wrote:

You replied selectively -- not nice.

Given that my position was that the case of "match[ing] an interface across a language bridge" was not plausible in the case of function declarations, I didn't think that the rest of the paragraph was relevant enough to quote. No other examples of cases in which it would be useful for a function name to be a keyword were given.

Excuses, excuses :-P.

Consider

function delete(foo) { ... } ... delete(bar);

Here the programmer has forgotten that 'delete' is a keyword. If
keywords are not allowed as declared names, then this mistake can be reported
at the function declaration. If they are allowed, then the mistake
cannot be reported (because "delete(bar)" is valid syntax), and will cause
unintended behaviour.

Good point (see, worth the time to reply -- at least in my opinion --
so: thanks!).

This seems not to be an issue in practice -- no bugs filed yet -- but
it is disturbing.

The costs are:

  • preventing implementations from reporting errors when a keyword is used unintentionally. This is a significant cost, especially for new programmers who may not be entirely familiar with the full keyword
    set.

In practice it has not proven so for JS1.7 users, but who knows? You
could be right that it would be a significant cost with more user
testing. I wouldn't assert that it "is significant" yet without
evidence.

What is now clearly significant, thanks to your reply, is the lack of
diagnostics for certain keywords when used as "callees" in "call
expressions". That reminds me of why opt-in was needed to add 'yield':
because it's used a formal parameter name and (IIRC) as a function name.

  • programs that rely on this change will fail to work on some ES3 implementations, when renaming the function would have been
    sufficient to allow them to work (if there is no other reliance on ES3.1).

This says the spec should not allow extensions that add keyword- unreserving contexts. I'm sure you agree ;-).

# David-Sarah Hopwood (17 years ago)

Brendan Eich wrote:

On Jan 20, 2009, at 2:09 PM, David-Sarah Hopwood wrote:

The costs are:

  • preventing implementations from reporting errors when a keyword is used unintentionally. This is a significant cost, especially for new programmers who may not be entirely familiar with the full keyword set.

In practice it has not proven so for JS1.7 users, but who knows? You could be right that it would be a significant cost with more user testing. I wouldn't assert that it "is significant" yet without evidence.

Any benefit due to being able to give functions keyword names has to be weighed against the cost of this lack of error reporting (and the compatibility issue below). The benefit is low, so the cost doesn't have to be particularly high, in order for the outcome to be against making this change.

  • programs that rely on this change will fail to work on some ES3 implementations, when renaming the function would have been sufficient to allow them to work (if there is no other reliance on ES3.1).

This says the spec should not allow extensions that add keyword-unreserving contexts. I'm sure you agree ;-).

I didn't say that this was a sufficient cost by itself to preclude such extensions. In the case of allowing property names to be keywords, for instance, we have a greater benefit because both the definition (in object literals) and its use (in member expressions) can be allowed.

Nevertheless, this is a significant compatibility/interoperability cost. IE7 doesn't appear to allow any keyword as a property name in either object literals or member expressions, for instance, so it will be a while before the ability to do this in ES3.1 is actually useful on the web [*]. That's a consideration for any extension, but more so for extensions that don't add any expressiveness to the language, and that a program could have avoided with a simple local renaming.

[*] User adoption of new IE versions seems painfully slow: www.w3schools.com/browsers/browsers_stats.asp, The only way I see that improving is if Microsoft change their browser upgrade policy.

# Brendan Eich (17 years ago)

On Jan 20, 2009, at 8:26 PM, David-Sarah Hopwood wrote:

  • programs that rely on this change will fail to work on some ES3 implementations, when renaming the function would have been
    sufficient to allow them to work (if there is no other reliance on ES3.1).

This says the spec should not allow extensions that add keyword-unreserving contexts. I'm sure you agree ;-).

I didn't say that this was a sufficient cost by itself to preclude
such extensions. In the case of allowing property names to be keywords, for instance, we have a greater benefit because both the definition (in object literals) and its use (in member expressions) can be allowed.

There's no way to quantify this greater benefit, at least as far as I
know. So it's more precise to say that there's no hazard of the kind
you pointed out where

function typeof(...) {...} ... typeof(x) ...

passes without error in old or new implementations (assuming keyword
function names are allowed).

The above could even be argued to be a feature for "upgrading" certain
keywords, provided they are unary operators always used (by
convention) with parenthesized operands! Again we have zero
quantification by which to conclude that this is less or greater a
benefit vs. cost. But it's a cost unique to the "keyword function"
approach, I agree. It does not come up with keywords as context- qualified property names where the context is unambiguos for uses as
well as definitions.

So what do we really know?

  • JS1.7 and JS1.8 have shipped without drawing bugzilla reports about
    the problem you pointed out.
  • On the other hand, it's not clear how useful keyword functions are
    if so named only for pretty-printing or self-calling reasons -- again
    no evidence has been gathered or quantified.
  • We do know that hazard you cite is unique to the "keyword function"
    proposal; it does not arise in the case of qualified property names in
    object initialisers and dotted expressions.

Using 1 bit of estimation, rounding conservatively, it seems the
benefits and costs of a prototype implementation of keyword functions
are both 0, and the hazard-cost of keyword functions compared to
qualified keyword properties is 1.

So again I agree we should leave out keyword functions. I was hoping
to get further agreement on the 3.1 spec prohibiting keyword functions
even as an extension (in chapter 16, if it does not already prohibit
this kind of extension). This prohibition can be debated independently
of any concern about compatibility with existing browsers.

In any case what's in 3.1 seems good to keep, and I didn't mean to
question it. I hope you are not suggesting qualified keyword
properties be removed. More below on general compatibility arguments
against expressiveness extensions.

Nevertheless, this is a significant compatibility/interoperability
cost. IE7 doesn't appear to allow any keyword as a property name in either object literals or member expressions, for instance, so it will be a while before the ability to do this in ES3.1 is actually useful on the web [*].

That's true of a number of ES3.1 features that can't be emulated fully
or at all. It's true of any future Harmony extensions. It's inevitable
in my view, and the best we can do is to keep the standard alive and
evolving in usable utility, not over-minimizing pessimistically, with
web developers participating and pushing browser vendors for greater
use of new versions over time.

That's a consideration for any extension, but more so for extensions that don't add any expressiveness to the language, and that a program could have avoided with a simple local renaming.

Expressiveness is worth something too. Weighing the trade-off against
short-term considerations is usually fatal to any longer-term progress.

We are not in this for the short-term, or there wouldn't be a new
version of IE in 2006 after none was planned following IE6 Service
Pack 1 in 2003, or a new version of ECMAScript in 2009. Five years
ago, before Firefox 1.0, these things seemed out of reach. Look how
far we've come since then. We should think ahead five years and build
on what has happened.

[*] User adoption of new IE versions seems painfully slow: www.w3schools.com/browsers/browsers_stats.asp,

That's just one source, and it may not distinguish IE6 from fake-IE6
(see en.wikipedia.org/wiki/Usage_share_of_web_browsers, AVG
Linkscanner).

IE6 peaked in the high 80% share in 2002-2003 and fell to just above
20% at the end of last year. For many lead-user or highly monetized
sites, IE6's share is so low that the sites' web developers do not
support it. I know a lot of Enterprise use remains behind firewalls.
But five more years of web browser and advanced web content competion
will continue the trend of the last five years, and put IE6 out of our
misery -- probably sooner, maybe in two years.

The only way I see that improving is if Microsoft change their browser upgrade policy.

Whether they do this or not, we should keep designing for the longer
term and not preemptively sacrifice expressiveness for short-term
compatibility, especially ersatz compatibility in the case of non- syntactic extensions that add new semantics which cannot be emulated
on old browsers. Such ersatz compatibility can lead developers into
making a security hole where none existed.