arrow syntax unnecessary and the idea that "function" is too long

Claus Reinke claus.reinke at talk21.com
Sun May 22 02:01:05 PDT 2011


> Because the LabelledStatement changes in 
> http://wiki.ecmascript.org/doku.php?id=strawman:arrow_function_syntax 
> restrict labels to prefix only LabelUsingStatements. I was 
> addressing the backward incompatibility here: ES1-5 allow 
> useless labels. You seemed to think that incompatibility was 
> important enough to require new label syntax, but I argued 
> that it is (a) not important; (b) caught by early error 
> during migration.

Ok, so you want to restrict label use. But syntax alone cannot
guarantee that a given label prefix is ever actually used, it can
only rule out alternatives that cannot possibly use the label. 
And introducing such syntactic restrictions on label use means 
that one can no longer insert labels without thinking about
whether they can be used because inserting unused labels
might require rewriting the code. In any case, the result is 
that both parser writers and developers have to think about 
the restrictions that make labeled Statements different from 
Statements. 

I still have a few blind spots where things that I thought
about for this class of language are not actually permitted 
by the Javascript grammar, so perhaps LabelUsingStatement 
won't introduce enough additional complexity to worry 
about. But, generally speaking, I'd prefer to remove
complexity from the grammar, rather than add it.

It isn't that I like labels, but if labels are permitted, I prefer 
them not introducing additional complexity that I have to 
think about. So my comments were based on not having
the LabelledStatement changes, addressing the ambiguity
in another way.

Without changes, any grammar that has ObjectLiteral and
Block as alternatives is ambiguous:

    ObjectLiteral | Block    // ambiguous

Assuming we want to resolve ambiguities by preferring
ObjectLiteral, we could write

    ObjectLiteral | (Block butnot ObjectLiteral)

where the right branch is the implicit grammar for what you 
are aiming to spec explicitly, by removing the ambiguous 
cases from Block, specifically from LabelledStatement, to
give us some form of RestrictedBlock that doesn't conflict
with ObjectLiteral. So we can combine both in arrow bodies

    ObjectLiteral | RestrictedBlock

(PEG-style grammars could make that even more implicit,
via ordered choice: anything that is a valid ObjectLiteral 
can no longer reach the second alternative)

The problem I have with that is that I need to think far
ahead to figure out whether I'm writing an ObjectLiteral
or a RestrictedBlock and that I need to be aware of whether 
the Statement I'm writing follows a label or not.

So I'm looking for a way to introduce a committed choice
based on limited lookahead instead. It seems that the
IdentifierName (PropertyName) vs Identifier (label) case
is the one that can lead to long lookaheads, so breaking
that seems a step forward. Hence the new-style labels.

It is not necessary to remove old-style labels right away,
because old code that uses them only uses old language
constructs (which never mix ObjectLiteral and Block). For
code that opts into Harmony, a deprecation warning for
old-style label seems appropriate, but we don't need to
force code rewrites of old code.

For any new language constructs that do mix ObjectLiteral 
and Block, such as arrow syntax, we can arrange that 
'{ Identifier : .. }' always defaults to ObjectLiteral, no matter 
what comes next. In these positions, old-style labels are 
useless, but new language constructs are only used in 
new code, so we  can ask developers to use new label 
syntax if they want  a Block starting with a label in such 
positions.

In grammar terms, the arbitrary lookahead alternative

    ObjectLiteral | (Block butnot ObjectLiteral)

turns into something like

    ObjectLiteral | (Block butnot ('{' (Identifier|StringLiteral) ':' .*)

If this works out, parsers and programmers can commit 
to one of the alternatives after a limited lookahead, no 
matter what comes next. Committed choice also means
no backtracking, so '{ empty: ; }' would be an invalid
ObjectLiteral, not a valid Block, if used as an arrow body
(while '{ :empty: ; }' would be an empty block). 

So there are pros and cons - the means of disambiguation 
are easier to understand, but not as expressive.

> Now I don't see any solution in adding new label syntax. 
> Having to parse the old one leaves us with the ambiguity. 
> What am I missing?

Old labels in old code don't use new features, like arrow
syntax, so the ambiguity does not surface. Old labels in 
new code using arrow syntax will be overlapped by object 
property names, so the ambiguity is resolved. New labels 
in new code using arrow syntax allow to override the
default ambiguity resolution.

>>>> but add labels starting with, say ':' (just to pick a prefix).
>>> We really don't want two label syntaxes, ..
>> 
>> Right. The old syntax could be deprecated (when opting in
>> for ES/next) - it also doesn't allow label parameters or
>> label variables.
> 
> Do you mean prohibited or deprecated? Usually deprecation 
> means a warning, obsolescence or prohibition means removal.

Deprecation, with removal not before ES/next/next.

Of course, changing label syntax might give the impression 
that labels are an encouraged feature, which isn't quite right.

> Yes, the strawman proposes to break such code. So requiring {; 
> or similar would be a simpler change and non-breaking in the 
> sense that one can rescue such code so it works in Harmony 
> as it used to, by adding one character. Good idea!

Thanks.

Claus
 


More information about the es-discuss mailing list