RFE: Allow newline when returning an anonymous object

# cowwoc (11 years ago)

Please let me know whether I've got the right mailing list.

I'd like to propose a change to ECMAScript. Right now the following syntax is required for returning an anonymous object:

return { key: "value" };

I would like the specification to also allow the following syntax:

return { key: "value" };

Meaning, allow a newline between "return" and the opening brace. Should I create an issue at bugs.ecmascript.org/enter_bug.cgi?product=ECMA-262 for tracking this?

Gili

-- View this message in context: mozilla.6506.n7.nabble.com/RFE-Allow-newline-when-returning-an-anonymous-object-tp316480.html Sent from the Mozilla - ECMAScript 4 discussion mailing list archive at Nabble.com.

# Oliver Hunt (11 years ago)

On May 28, 2014, at 11:10 AM, cowwoc <cowwoc at bbs.darktech.org> wrote:

I would like the specification to also allow the following syntax:

return { key: "value" };

This is currently valid syntax, and has an entirely different behaviour (and side effects) from returning an object literal. This means that even if we wanted to we could not change that behaviour without potentially breaking existing content.

That said our reason for the required newline is that it provides a mechanism to disambiguate the grammar and semantics of object literal vs. block statements.

The following for instance has totally different behaviour depending on whether the new line is used:

if (foo) return { L: print(something) }

The only way to disambiguate this in the general case is to have a rule such as <no newline> to allow us to be sure that the opening brace is in an expression context and not a statement.

# cowwoc (11 years ago)

Oliver Hunt-2 wrote

On May 28, 2014, at 11:10 AM, cowwoc <

cowwoc at .darktech

wrote:

I would like the specification to also allow the following syntax:

return { key: "value" };

This is currently valid syntax, and has an entirely different behaviour (and side effects) from returning an object literal. This means that even if we wanted to we could not change that behaviour without potentially breaking existing content.

That said our reason for the required newline is that it provides a mechanism to disambiguate the grammar and semantics of object literal vs. block statements.

The following for instance has totally different behaviour depending on whether the new line is used:

if (foo) return { L: print(something) }

The only way to disambiguate this in the general case is to have a rule such as <no newline> to allow us to be sure that the opening brace is in an expression context and not a statement.

--Oliver

Hi Oliver,

Excuse my ignorance, but can you explain (or point me to a layman explanation) of the difference between the two forms?

Thanks, Gili

-- View this message in context: mozilla.6506.n7.nabble.com/RFE-Allow-newline-when-returning-an-anonymous-object-tp316480p316482.html Sent from the Mozilla - ECMAScript 4 discussion mailing list archive at Nabble.com.

# Oliver Hunt (11 years ago)

On May 28, 2014, at 11:23 AM, cowwoc <cowwoc at bbs.darktech.org> wrote:

if (foo) return { L: print(something) }

The only way to disambiguate this in the general case is to have a rule such as <no newline> to allow us to be sure that the opening brace is in an expression context and not a statement.

--Oliver

Hi Oliver,

Excuse my ignorance, but can you explain (or point me to a layman explanation) of the difference between the two forms?

I'm not sure what you mean by two forms - i'm assuming that you mean that you're interpreting the {}'s in both

return {}

and

return {}

As being object literals, when in fact the second is a return statement, followed by a block statement.

This ambiguity is why the opening brace is only consider an object literal if we are already in an expression context. If you are not in an expression context, you must be starting a statement, and so the open brace is the start of a block statement.

What you're asking for is grammatically ambiguous in a way that would potentially break existing content, and (generally) leads to really interesting parsing behaviour.

# cowwoc (11 years ago)

On 28/05/2014 2:33 PM, Oliver Hunt wrote:

On May 28, 2014, at 11:23 AM, cowwoc <cowwoc at bbs.darktech.org <mailto:cowwoc at bbs.darktech.org>> wrote:

if (foo) return { L: print(something) }

The only way to disambiguate this in the general case is to have a rule such as <no newline> to allow us to be sure that the opening brace is in an expression context and not a statement.

--Oliver

Hi Oliver,

Excuse my ignorance, but can you explain (or point me to a layman explanation) of the difference between the two forms?

I'm not sure what you mean by two forms - i'm assuming that you mean that you're interpreting the {}'s in both

return {}

and

return {}

As being object literals, when in fact the second is a return statement, followed by a block statement.

This ambiguity is why the opening brace is only consider an object literal if we are already in an expression context. If you are not in an expression context, you must be starting a statement, and so the open brace is the start of a block statement.

What you're asking for is grammatically ambiguous in a way that would potentially break existing content, and (generally) leads to really interesting parsing behaviour.

--Oliver

Don't we use a semicolon to denote the end of an expression context? Perhaps I'm missing something, but I see no ambiguity in the example you gave. I expect:

return {};

and

return {};

to return an object literal, whereas:

return; {}

or

return; {}

denote a return expression followed by a block.

Gili

# Brendan Eich (11 years ago)

Oliver Hunt wrote:

What you're asking for is grammatically ambiguous in a way that would potentially break existing content, and (generally) leads to really interesting parsing behaviour.

As Doug Crockford has argued, this is why K&R style is better in JS: always put the { at the end of the line whose first token starts the statement.

if (C) { . . . }

and not

if (C) { . . . }

# Oliver Hunt (11 years ago)

On May 28, 2014, at 11:39 AM, cowwoc <cowwoc at bbs.darktech.org> wrote:

Don't we use a semicolon to denote the end of an expression context? Perhaps I'm missing something, but I see no ambiguity in the example you gave. I expect:

return {};

and

return {};

to return an object literal, whereas:

return; {}

or

return; {}

denote a return expression followed by a block.

No, the semicolon is not relevant as it is optional, the rules for ASI result in

return {}

being converted to return ; {};

If you remove the newline restriction from return then ASI becomes ambiguous as well.

# cowwoc (11 years ago)

On 28/05/2014 2:42 PM, Brendan Eich wrote:

Oliver Hunt wrote:

What you're asking for is grammatically ambiguous in a way that would potentially break existing content, and (generally) leads to really interesting parsing behaviour.

As Doug Crockford has argued, this is why K&R style is better in JS: always put the { at the end of the line whose first token starts the statement.

if (C) { . . . }

and not

if (C) { . . . }

/be

That's an unfortunate side-effect. I think that developers should be able to pick their own code styles. After all, most of these choices are subjective. Anyway, thanks for the head's up.

Gili

# cowwoc (11 years ago)

On 28/05/2014 2:43 PM, Oliver Hunt wrote:

On May 28, 2014, at 11:39 AM, cowwoc <cowwoc at bbs.darktech.org> wrote:

Don't we use a semicolon to denote the end of an expression context? Perhaps I'm missing something, but I see no ambiguity in the example you gave. I expect:

return {};

and

return {};

to return an object literal, whereas:

return; {}

or

return; {}

denote a return expression followed by a block. No, the semicolon is not relevant as it is optional, the rules for ASI result in

return {}

being converted to return ; {};

If you remove the newline restriction from return then ASI becomes ambiguous as well.

--Oliver

Wow, what a mess. I've been pretty methodical about semicolons in my code so I forgot about this "feature" :)

I'm not a fan of ASI, but in light of your example I agree there is ambiguity. Thanks for the clarification.

You might want to consider killing off ASI one day, if "use strict" is enabled ;)

Gili

# Oliver Hunt (11 years ago)

On May 28, 2014, at 11:48 AM, cowwoc <cowwoc at bbs.darktech.org> wrote:

That's an unfortunate side-effect. I think that developers should be able to pick their own code styles. After all, most of these choices are subjective. Anyway, thanks for the head's up.

They can choose their own style, just not their own syntax.

# Tab Atkins Jr. (11 years ago)

On Wed, May 28, 2014 at 11:51 AM, cowwoc <cowwoc at bbs.darktech.org> wrote:

Wow, what a mess. I've been pretty methodical about semicolons in my code so I forgot about this "feature" :)

I'm not a fan of ASI, but in light of your example I agree there is ambiguity. Thanks for the clarification.

Remember the general rule: semicolons are always automatically inserted at the end of lines unless doing so would cause a syntax error on that line or the next.

That's why, for example, you can break method chains across lines on either side of the period:

foo().bar() .baz()

or

foo().bar(). baz()

because a semicolon between the lines would cause a syntax error in either. But blocks/object literals are different, so you need to start the object literal on the first line.

# cowwoc (11 years ago)

On 28/05/2014 2:59 PM, Tab Atkins Jr. wrote:

On Wed, May 28, 2014 at 11:51 AM, cowwoc <cowwoc at bbs.darktech.org> wrote:

Wow, what a mess. I've been pretty methodical about semicolons in my code so I forgot about this "feature" :)

I'm not a fan of ASI, but in light of your example I agree there is ambiguity. Thanks for the clarification. Remember the general rule: semicolons are always automatically inserted at the end of lines unless doing so would cause a syntax error on that line or the next.

That's why, for example, you can break method chains across lines on either side of the period:

foo().bar() .baz()

or

foo().bar(). baz()

because a semicolon between the lines would cause a syntax error in either. But blocks/object literals are different, so you need to start the object literal on the first line.

~TJ

That's a good/simple explanation. Thank you! :)

Gili

# Brendan Eich (11 years ago)

Tab Atkins Jr. wrote:

Remember the general rule: semicolons are always automatically inserted at the end of linesunless doing so would cause a syntax error on that line or the next.

No, this is not accurate. Consider

A (B);

Inserting a semicolon as you wrote:

A; (B):

does not make a syntax error, but it is not what ASI does, and doing so would break valid JS programs.

ASI is an error correction procedure plus those "restricted productions" (including the return statement's production).

# Brendan Eich (11 years ago)

Oliver Hunt wrote:

That's an unfortunate side-effect. I think that developers should be able to pick their own code styles. After all, most of these choices are subjective. Anyway, thanks for the head's up.

They can choose their own style, just not their own syntax.

Right, and syntax can restrict style (consider Python).

A bunch of us old timers have come around to the idea that languages should dictate style harder, to avoid pointless style wars and attendant patching woes. Even without too much restrictiveness, languages lately tend to grow tools to enforce canonical style (e.g., gofmt).

K&R style for JS is best. I'm an old C hacker.