Skip to content
This repository has been archived by the owner on Feb 19, 2018. It is now read-only.

CS2 Discussion: Features: Spread syntax triple dots on either right or left #85

Closed
GeoffreyBooth opened this issue May 30, 2017 · 25 comments

Comments

@GeoffreyBooth
Copy link
Collaborator

CoffeeScript’s spread syntax was adopted into ES2015, but they flipped the position of the dots from the right to the left:

foo args... # foo(...args);

We can’t flip them to the left in CoffeeScript without needlessly breaking lots of legacy code, but what about allowing the dots on either side?

foo args... # foo(...args);
# or
foo ...args # foo(...args);
@mrmowgli
Copy link

mrmowgli commented May 30, 2017 via email

@YamiOdymel
Copy link

+1 for this, since both are doing the same thing. But is it possible to use the spread syntax with the functions so I can do things like this? (it's a very common usage in Vue.js)

export default
    name   : 'CounterBlock'
    methods:
        ...mapActions
            increment : counter.actions.increment
            set       : counter.actions.set
            fetchCount: counter.actions.fetchCount
    computed:
        ...mapGetters
            total: counter.getters.total

It would be so elegant.


with the current coffeescript@next:

export default {
    name: 'CounterBlock'
    methods: Object.assign {}, mapActions
            increment : counter.actions.increment,
            set       : counter.actions.set,
            fetchCount: counter.actions.fetchCount
    computed: Object.assign {}, mapGetters
            total: counter.getters.total
}

with ES6:

export default {
    name: 'CounterBlock',
    methods: {
        ...mapActions({
            increment : counter.actions.increment,
            set       : counter.actions.set,
            fetchCount: counter.actions.fetchCount
        })
    },
    computed: {
        ...mapGetters ({
            total: counter.getters.total
        })
    },
}

@GeoffreyBooth
Copy link
Collaborator Author

@YamiOdymel You don’t need the { after export default since 1.12.6 or 2.0.0-beta2.

It looks like you’re asking for the destructuring object spread syntax, which is in progress at jashkenas/coffeescript#4493. That PR could use some help if you have time to contribute.

My intention with the proposal for this thread is just about syntax, that ... should behave the same way whether it’s on the right or left of an identifier. This is separate from destructuring object spreads; once we add support for that, and assuming this left/right proposal is also implemented, then destructured object spreads would be possible from either the right or left.

@connec
Copy link

connec commented May 30, 2017

I'd rather not have two syntaxes for the same thing. I get the reasons for switching, but if they're so compelling maybe we should just move to leading ...?

@GeoffreyBooth
Copy link
Collaborator Author

If we're not going to have both then we need to keep with the dots on the right. No point in introducing a breaking change for this.

But why not have both? There are plenty of places where we have multiple syntaxes for the same thing.

@edemaine
Copy link

I agree that having both would be nice. I'd rather not change all my legacy code, but I see readability advantages to having it first.

@connec
Copy link

connec commented May 30, 2017

There are plenty of places where we have multiple syntaxes for the same thing.

Any examples you're thinking of? (I don't doubt there are, but I'm drawing a blank just now 😓)

I guess I wouldn't say that's a great reason for adding more 😛 I could get behind supporting both with a deprecation maybe? What if someone tried to put both? 😱

@edemaine
Copy link

Perhaps most compelling examples:

f x
f(x)
not x or y and yes
!x || y && true
this and this.foo
@ && @foo

Other examples:

[1,2,3]
[
  1
  2
  3
]
(if x then f(x)) for x in L
for x in L
  if x
    f(x)

(though these serve somewhat different roles: single-line vs. multi-line)

@GeoffreyBooth
Copy link
Collaborator Author

I was thinking of and versus &&, or versus ||, etc. would be the most relevant examples. Those follow the same principle of idiomatic CoffeeScript versus JS equivalent. We don’t deprecate &&, so I don’t know why we would deprecate either of the dot sides.

I guess I wouldn’t say that’s a great reason for adding more

Yes, though this is more of just a convenience. It is annoying when going back and forth between CS and ES to have to remember to flip the dots. Allowing the dots on the left also lets people write CS that’s closer to the generated JS, for those who care.

What if someone tried to put both?

That is a good point. I guess . . . the same as if they had put the dots on only one side? Or we could just throw an error. It’s a pretty dumb edge case.

@connec
Copy link

connec commented May 30, 2017

The boolean operators are a pretty convincing example tbf, and postfix conditionals are a similar case as well I suppose.

I think an error would be better for ... but you're right that if we can get it through the parser that should be easy enough to check. I have no idea how to make the parser accept this, though. Every time I've touched splats in the grammar I've almost immediately hit parser ambiguities 😢

@edemaine
Copy link

I'm moderately hopeful that splats at the beginning will be actually be a lot easier to avoid parser ambiguities, because the first token immediately disambiguates the case. (But I'm no expert here.)

zdenko pushed a commit to GeoffreyBooth/coffeescript that referenced this issue Jun 4, 2017
- Clean up "Assign" and moved all logic for object rest properties in single method (compileObjectDestruct).
- Add helper function "objectWithoutKeys" to the "UTILITIES" for use with object rest properties,
  e.g. {a, b, r...} = obj => {a, b} = obj, r = objectWithoutKeys(...)
- Clean up "Obj" and moved all logic for object spread properties in single method (compileSpread).
- Clean up "Code".
- Add method "hasSplat" to "Obj" and "Value" for checking if Obj contains the splat.
- Enable placing spread syntax triple dots on either right or left, per jashkenas#85 (coffeescript6/discuss#85)
@zdenko
Copy link

zdenko commented Jun 4, 2017

@GeoffreyBooth I added option to place spread syntax on both sides in my last commit to PR #4493.

@jashkenas
Copy link

Please just pick one side or the other — definitely not either.

CoffeeScript 2.0 is a fine time to make the change to ...spread, if you're going to more closely align with ES6.

@GeoffreyBooth
Copy link
Collaborator Author

@jashkenas One of the goals of CS2 is to minimize breaking changes, even when that means we’re less aligned with ES6. We’re not renaming for…of, for example. That’s why I consider simply changing the side to be off the table; just look at the number of places that would affect the compiler codebase, for example.

So if you accept that we can’t just switch sides, what’s the harm in allowing both sides? How is that different from allowing both and and &&?

@jashkenas
Copy link

jashkenas commented Jun 5, 2017

Since you're running point on this, do what you think is best ;)

One can also imagine doing a full-blown deprecation cycle: Where in 2.0, both sides are allowed, but only ...x is documented on CoffeeScript.org. Later, in 2.1, x... begins to log deprecation warnings, and later, in 2.whatever or 3, x... is finally removed, with a pleasant error.

@GeoffreyBooth
Copy link
Collaborator Author

At the moment I’m much more worried about declining marketshare than I am about logical purity, and I think there’s much greater risk of people abandoning CoffeeScript or not choosing it for a project if 2.0 is viewed as a major breaking-change release, like Python 2 to 3. If the upgrade path to 2 is too difficult, many people may choose to use Decaffeinate instead, especially if they think there might be further breaking changes in CoffeeScript’s future. One thing that ES has over us is that as long as you stick to Stage 4 features, backward compatibility is near-sacrosanct. We’re essentially competing with ES at this point, in terms of convincing developers to choose one or the other for a project, and so I worry about lagging behind ES in this regard.

That said, greater ES alignment is definitely something we should consider and discuss, and your path sounds like the right way to go about it. I would save that discussion for after we get 2.0.0 out the door, though, so that there’s at least that version for people to upgrade to before we start deprecating things.

@objectkit
Copy link

As an annoying absent armchair design committee member, @GeoffreyBooth , you have done, and are continuing to tackle and balance many pain points and burdens simultaneously, so multilateral respect whatever direction you choose. Simply from a language design perspective, my hand is in the air - I would like to see a break and alignment with ES6 on this matter. From a maintenance perspective, I assume the practical advantage of both would be in relation to proffering an allowance to those refactoring existing CS1 applications. In that regard, with so many under the hood changes to the ES6 output, I am curious about the utility of that. I personally see CS2 as a fresh start. Carrying both approaches invites legacy. Its just a personal opinion. I don't mean to distract.

@GeoffreyBooth
Copy link
Collaborator Author

We would piss off a lot of people (for very little gain) by removing the dots on the right. So for 2.0.0 we need to at least keep those, if not allow both.

For 3.0.0 we should discuss a cleaning up of the language, refactoring the dots and things like for…of and maybe even the implicit return and/or let/const/block scope. But I think we need at least one major release that pulls all the legacy projects up to the modern ES world, before we introduce a truly breaking-change release that is a rethink of the language (and either isn’t intended for upgrades from 2, or will require an upgrade tool and major refactoring). The discussion would have to include whether the gains from such a refactor are even worth it, considering the schism it would create with projects that never upgrade. That’s a much bigger discussion, that I’d like to delay until after we get 2.0.0 out the door if people don’t mind 😄

@rattrayalex
Copy link
Contributor

A deprecation cycle, as proposed by @jashkenas, sounds to me like the standard approach (in a good way).

I sort of imagine that people would rather get the deprecation message sooner rather than later, though, as "the move to 2.0" is sure to get some amount of refactoring budget for any software project (everybody would expect it might take some work), and it'd be more bothersome to have to deal with this detail later.

So deprecating at the start of 2.0 is what I'd advocate for. Certainly not a strong opinion, just sharing the thought.

@GeoffreyBooth
Copy link
Collaborator Author

Personally I don’t see the need to deprecate the dots on the right. I think dots on the right make more sense, since CoffeeScript syntax is meant to emulate readable English and in English we write stuff like items.... If I were the dictator of syntax, I would allow either side but keep the dots on the right as the only documented option and the preferred style. It’s not like we’re going to deprecate and in favor of &&, just because ES uses &&.

What I had in mind for a deprecation cycle (not that I’m necessarily favor of this, just that we should discuss it post-2.0.0) are suggestions like @jashkenas’ about switching to full block scoping.

@objectkit
Copy link

objectkit commented Jun 6, 2017

I think we need at least one major release that pulls all the legacy projects up to the modern ES world, before we introduce a truly breaking-change release that is a rethink of the language... That’s a much bigger discussion, that I’d like to delay until after we get 2.0.0 out the door if people don’t mind

👍

@GeoffreyBooth You are absolutely right. Thats a much better perspective for the here and now. Future cycles can address change in a more orderly fashion. Your mention of CS supporting natural language idioms has good bearing... go for it as you see fit. Namaste 🙏

GeoffreyBooth added a commit to jashkenas/coffeescript that referenced this issue Jun 30, 2017
* Don’t confuse the syntax highlighter

* Comment Assign::compilePatternMatch a bit

* Assignment expressions in conditionals are a bad practice

* Rename `wrapInBraces` to `wrapInParentheses`, to set the stage for future `wrapInBraces` that uses `{` and `wrapInBrackets` that uses `[`

* Correct comment

* object destructuring

* Allow custom position of the rest element.

* Output simple array destructuring assignments to ES2015

* Output simple object destructured assignments to ES2015

* Compile shorthand object properties to ES2015 shorthand properties

This dramatically improves the appearance of destructured imports.

* Don’t confuse the syntax highlighter

* Comment Assign::compilePatternMatch a bit

* Assignment expressions in conditionals are a bad practice

* Rename `wrapInBraces` to `wrapInParentheses`, to set the stage for future `wrapInBraces` that uses `{` and `wrapInBrackets` that uses `[`

* object destructuring

* Allow custom position of the rest element.

* rest element in object destructuring

* rest element in object destructuring

* fix string interpolation

* merging

* fixing splats in object literal

* Rest element in parameter destructuring

* merging with CS2

* merged with CS2

* Add support for the object spread initializer. https://github.com/tc39/proposal-object-rest-spread/blob/master/Spread.md

* Fix misspellings, trailing whitespace, other minor details

* merging with beta2

* refactor object spread properties

* small fix

* - Fixed object spread function parameters.
- Clean up "Assign" and moved all logic for object rest properties in single method (compileObjectDestruct).
- Add helper function "objectWithoutKeys" to the "UTILITIES" for use with object rest properties,
  e.g. {a, b, r...} = obj => {a, b} = obj, r = objectWithoutKeys(...)
- Clean up "Obj" and moved all logic for object spread properties in single method (compileSpread).
- Clean up "Code".
- Add method "hasSplat" to "Obj" and "Value" for checking if Obj contains the splat.
- Enable placing spread syntax triple dots on either right or left, per #85 (coffeescript6/discuss#85)

* Fixed typos

* Remove unused code

* Removed dots (e.g. splat) on the left side from the grammar

* Initial release for deep spread properties, e.g. obj2 = {obj.b..., a: 1} or {obj[b][c]..., d: 7}
Tests need to be prepared!

* 1. Object literal spread properties

Object literals:
- obj = { {b:{c:{d:1}}}..., a:1 }

Parenthetical:
- obj = { ( body ), a:1 }
- obj = { ( body )..., a:1 }

Invocation:
- obj = { ( (args) -> ... )(params), a:1 }
- obj = { ( (args) -> ... )(params)..., a:1 }
- obj = { foo(), a:1 }
- obj = { foo()..., a:1 }

2. Refactor, cleanup & other optimizations.

* Merged with 2.0

* Cleanup

* Some more cleanup.

* Fixed error with freeVariable and object destructuring.

* Fixed errors with object spread properties.

* Improvements, fixed errors.

* Minor improvement.

* Minor improvements.

* Typo.

* Remove unnecessary whitespace.

* Remove unnecessary whitespace.

* Changed few "assertErrorFormat" tests since parentheses are now allowed in the Obj.

* Whitespace cleanup

* Comments cleanup

* fix destructured obj param declarations

* refine fix; add test

* Refactor function args ({a, b...})

* Additional tests for object destructuring in function argument.

* Minor improvement for object destructuring variable declaration.

* refactor function args ({a, b...}) and ({a, b...} = {}); Obj And Param cleanup

* fix comment

* Fix object destructuring variable declaration.

* more tests with default values

* fix typo

* Fixed default values in object destructuring.

* small fix

* Babel’s tests for object rest spread

* Style: spaces after colons in object declarations

* Cleanup comments

* Simplify Babel tests

* Fix comments

* Fix destructuring with splats in multiple objects

* Add test for default values in detsructuring assignment with splats

* Handle default values when assigning to object splats

* Rewrite traverseRest to fix handling of dynamic keys

* Fix double parens around destructuring with splats

* Update compileObjectDestruct comments

* Improve formatting of top-level destructures with splats and tidy parens

* Added a bigger destructuring-with-defaults test and fixed a bug

* Refactor destructuring grammar to allow additional forms

* Add a missing case to ObjSpreadExpr

* These tests shouldn’t run in the browser

* Fix test.html
@laurentpayot
Copy link

I think dots on the right make more sense, since CoffeeScript syntax is meant to emulate readable English and in English we write stuff like items....

➕ 💯

GeoffreyBooth added a commit to jashkenas/coffeescript that referenced this issue Jun 30, 2017
* Don’t confuse the syntax highlighter

* Comment Assign::compilePatternMatch a bit

* Assignment expressions in conditionals are a bad practice

* Rename `wrapInBraces` to `wrapInParentheses`, to set the stage for future `wrapInBraces` that uses `{` and `wrapInBrackets` that uses `[`

* Correct comment

* object destructuring

* Allow custom position of the rest element.

* Output simple array destructuring assignments to ES2015

* Output simple object destructured assignments to ES2015

* Compile shorthand object properties to ES2015 shorthand properties

This dramatically improves the appearance of destructured imports.

* Don’t confuse the syntax highlighter

* Comment Assign::compilePatternMatch a bit

* Assignment expressions in conditionals are a bad practice

* Rename `wrapInBraces` to `wrapInParentheses`, to set the stage for future `wrapInBraces` that uses `{` and `wrapInBrackets` that uses `[`

* object destructuring

* Allow custom position of the rest element.

* rest element in object destructuring

* rest element in object destructuring

* fix string interpolation

* merging

* fixing splats in object literal

* Rest element in parameter destructuring

* merging with CS2

* merged with CS2

* Add support for the object spread initializer. https://github.com/tc39/proposal-object-rest-spread/blob/master/Spread.md

* Fix misspellings, trailing whitespace, other minor details

* merging with beta2

* refactor object spread properties

* small fix

* - Fixed object spread function parameters.
- Clean up "Assign" and moved all logic for object rest properties in single method (compileObjectDestruct).
- Add helper function "objectWithoutKeys" to the "UTILITIES" for use with object rest properties,
  e.g. {a, b, r...} = obj => {a, b} = obj, r = objectWithoutKeys(...)
- Clean up "Obj" and moved all logic for object spread properties in single method (compileSpread).
- Clean up "Code".
- Add method "hasSplat" to "Obj" and "Value" for checking if Obj contains the splat.
- Enable placing spread syntax triple dots on either right or left, per #85 (coffeescript6/discuss#85)

* Fixed typos

* Remove unused code

* Removed dots (e.g. splat) on the left side from the grammar

* Initial release for deep spread properties, e.g. obj2 = {obj.b..., a: 1} or {obj[b][c]..., d: 7}
Tests need to be prepared!

* 1. Object literal spread properties

Object literals:
- obj = { {b:{c:{d:1}}}..., a:1 }

Parenthetical:
- obj = { ( body ), a:1 }
- obj = { ( body )..., a:1 }

Invocation:
- obj = { ( (args) -> ... )(params), a:1 }
- obj = { ( (args) -> ... )(params)..., a:1 }
- obj = { foo(), a:1 }
- obj = { foo()..., a:1 }

2. Refactor, cleanup & other optimizations.

* Merged with 2.0

* Cleanup

* Some more cleanup.

* Fixed error with freeVariable and object destructuring.

* Fixed errors with object spread properties.

* Improvements, fixed errors.

* Minor improvement.

* Minor improvements.

* Typo.

* Remove unnecessary whitespace.

* Remove unnecessary whitespace.

* Changed few "assertErrorFormat" tests since parentheses are now allowed in the Obj.

* Whitespace cleanup

* Comments cleanup

* fix destructured obj param declarations

* refine fix; add test

* Refactor function args ({a, b...})

* Additional tests for object destructuring in function argument.

* Minor improvement for object destructuring variable declaration.

* refactor function args ({a, b...}) and ({a, b...} = {}); Obj And Param cleanup

* fix comment

* Fix object destructuring variable declaration.

* more tests with default values

* fix typo

* Fixed default values in object destructuring.

* small fix

* Babel’s tests for object rest spread

* Style: spaces after colons in object declarations

* Cleanup comments

* Simplify Babel tests

* Fix comments

* Fix destructuring with splats in multiple objects

* Add test for default values in detsructuring assignment with splats

* Handle default values when assigning to object splats

* Rewrite traverseRest to fix handling of dynamic keys

* Fix double parens around destructuring with splats

* Update compileObjectDestruct comments

* Improve formatting of top-level destructures with splats and tidy parens

* Added a bigger destructuring-with-defaults test and fixed a bug

* Refactor destructuring grammar to allow additional forms

* Add a missing case to ObjSpreadExpr

* These tests shouldn’t run in the browser

* Fix test.html

* Fix docs scroll position getting screwed up by CodeMirror initialization

* Breaking change documentation about => (fixes #4593)

* Spread/rest syntax documentation

* Documentation about bound class methods

* 2.0.0-beta3 changelog

* Add note about ‘lib’

* Fix accidentally converting this to tabs

* Bump version to 2.0.0-beta3

* Update annotated source and test.html
@GeoffreyBooth
Copy link
Collaborator Author

@zdenko did you want to submit an isolated PR for the ‘dots on either side’ work?

@zdenko
Copy link

zdenko commented Jul 7, 2017

@GeoffreyBooth yes: #4606

@coffeescriptbot coffeescriptbot changed the title Spread syntax triple dots on either right or left CS2 Discussion: Features: Spread syntax triple dots on either right or left Feb 19, 2018
@coffeescriptbot
Copy link
Collaborator

Migrated to jashkenas/coffeescript#4978

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests