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

CS2 Discussion: Output: Destructuring assignment #18

Closed
Asc2011 opened this issue Jul 31, 2016 · 22 comments
Closed

CS2 Discussion: Output: Destructuring assignment #18

Asc2011 opened this issue Jul 31, 2016 · 22 comments

Comments

@Asc2011
Copy link

Asc2011 commented Jul 31, 2016

Destructuring assignment

the example from the CS-hompage run with CS 1.10 / browser(chrome) / latest

futurists =
  sculptor: "Umberto Boccioni"
  painter:  "Vladimir Burliuk"
  poet:
    name:   "F.T. Marinetti"
    address: [
      "Via Roma 42R"
      "Bellagio, Italy 22021"
    ]

{poet: {name, address: [street, city]}} = futurists
console.log futurists

console.log "'street' defined ?", street?, (street if street?)
console.log "'poet' defined ?", poet?, (poet if poet?)
console.log "broken CS ? why is 'poet' in 'ref' ?", eval('ref').name

I'm bringing this up, 'cos i can't figue out the current the status of 'destructuring assignments'.
I'm not sure if that is expected behaviour. I'd expect 'poet' to be avail in local-scope.
There has been some discussions during 2013 at CS-github.issues.page eg. Issue 3500, Issue 3225

I'd like to be able to assign to a local var :

b = {}
b.{poet: {name, address: [street, city]}} = futurists

This has been proposed before - the regarding issue(s) is/are solved | closed. The status is unclear to me ?
So i vote for it in CS6.

@carlsmith
Copy link

carlsmith commented Aug 3, 2016

Thank you for getting involved. No discussion has taken place here yet on destructuring assignments, so it's good that you've started that conversation.

My only thought at this stage is that CoffeeScript destructuring syntax is too cryptic, so it would be nice to simplify things. I'd love to see a comprehensive proposal for what the exact syntax should be. If it's simple enough to be a good spec, it shouldn't be that difficult to explain.

As for what you're specifically asking for, to be honest, I don't understand the proposal or what this code aught to do:

b = {}
b.{poet: {name, address: [street, city]}} = futurists

I'd rather force assignments to be broken up across a few lines than have this super cryptic syntax. It's impossible to figure out what the code does from just looking at it and knowing CoffeeScript.

@rattrayalex
Copy link
Contributor

Yes, welcome @Asc2011 !

Personally I find destructuring assignment an exciting feature, and one I've been missing in ES6.

I think nested destructrucing assignment might be too complex, as @carlsmith perhaps alludes to; I can't tell if the example is setting b.name, b.street, and b.city or b.poet.name, b.poet.address.street and b.poet.address.city. It looks more like the latter, but the former matches general nested destructuring more closely. And I'd really prefer not to have semantics that look like ES6 but have differing behavior.

That said,

a = {.... c: 3, d: 4, ....}
b.{ c, d } = a

seems quite clear and useful to me. I'd also consider

a = {.... c: 3, d: 4, ....}
b{ c, d } = a

Any other ideas?

Thoughts?

@JimPanic
Copy link
Contributor

JimPanic commented Aug 5, 2016

I love what ES calls destructuring assignment. In Elixir it's called pattern matching and it is the utter most awesome feature of the language.

Destructured assignment should stay simple, it mimics mathematical equations and are quite intuitive to follow as-is. I think nested to-property assignments like this should be implemented at runtime, not in the syntax.

@Asc2011
Copy link
Author

Asc2011 commented Aug 5, 2016

sry for being late on this :) I did some homework and found we are almost there.
The attached coffee-file contains some book-examples from chapter 10/'Destructuring' of the book Exploring ES6. A not working-feature is console.error, similar is console.warn and console.log for feature seems fully supported. I tried this using CoffeeConsole (1.10) on Chrome/latest.

Most examples work in CS as expected :

  • in for-loops
  • coercion
  • using default-values

not working :

  • computed property-keys
  • elision ( on arrays ) see chapter 10.7

to watch out for because the syntax is dangerously similar :

  • ES6-'REST'-operator and 'SPREAD'-operator '...'
  • are syntactically equal to the CS-splats-oprator '...'

I'm happy with how things work right now and hey this is not scala. In the future maybe 'computed-property.keys' make sense ? For now i can do that with backticks. I'd like to see destructuring on Iterators/Sets someday. But more important would be a 'harmonized' for-loop on iterators, as already proposed here.
I'd offer to write a Jasmine-spec, if that helps. Just to keep the overview on which features work, work with minor changes (REST/SPREAD/Splat)-operator or do not work at all.
I mentioned Scala, because i was impressed by the method, how they decided on language-features. They reasearched which code-errors did statistically happen most frequently in java-land. NPE was clearly the leader here. Following this idea, i'd say problems with destructuring are rare to me and i just learned that most of the features work as expected. The 'for-in/of'-loop or yet the impossible for-loop on Sets bite me all the time.
Regarding destructuring-assignments I'd propose to stay as close to the ES6-standard as possible.

greets andreas

destructuring_test.coffee.txt

@Asc2011
Copy link
Author

Asc2011 commented Aug 5, 2016

@carlsmith @rattrayalex

The idea was to end up with the poet
b = { name: "F.T. Marinetti" address: [ "Via Roma 42R" "Bellagio, Italy 22021" ] }
now i did my homework and i think all's well. See my answer above.
Extracting from deeply-nested objects might become a topic later on.

greets andreas

@rattrayalex
Copy link
Contributor

Thanks Andreas!

I'm not quite sure I've followed everything here; where does this leave us?

@Asc2011
Copy link
Author

Asc2011 commented Aug 7, 2016

Hello alex @rattrayalex,
let's stay focussed on the priorities as discussed on Gitter - main targets should be ES6-modules and ES6-classes. The destructuring-assignments as defined in ES6 are to some extend already usable as-is in CS 1.10.
It seems that the CS-Splat-operator ... somehow collides with what ES6 defines as 'SPREAD'- and 'REST'-operators - as both use the ...-notation. So one might consider redefining/changing the CS-Splat-operator in favour of the ES6-operators ? That would break existing code. I'd propose to redefine the CS-Splat == ___ and introduce Spread-operator == ... and Rest-operator == ... as defined by ES6-spec. Or maybe not - buts thats for later.

The syntax i had in mind as well as your example from above

a = {.... c: 3, d: 4, ....} b.{ c, d } = a

represent new language-features. You can't do a assignments newVal.{ poet } = futurists in ES6-spec.

BTW: we should fix this forum, so that one can put in indented code-examples ?!

So i see this issue moving down the prio-list :

  1. fix modules & classes
  2. fix other important things maybe implementing ES6-destructuring-features that are currently not supported. see above e.g. 'elision' or 'computed property-keys'
  3. discuss/test new language-features -> belongs to wish-list

I'll keep an eye on destructuring-assignments and will maintain the 'compatabillity-chart' based on the tests from the attached-file above. As a CS-user i'd welcome a chart that shows which features of ES-specs are fully/partially/not supported. Like the browser-vendors do it.

greets andreas

@mrmowgli
Copy link

This is an interesting area for me as well. I like the way ES6 has implemented the destructuring and the spread and rest facilities, and I think CS6 should make an attempt to adopt the functionality if not directly the syntax. The rules for destructuring should match the ES6 versions.

It's a shame they used portions of CS for language features, because it does break a lot of the code. Particularly the splats. Perhaps an alternate with the .... as a substitute would work.

Realistically though this might need to be a breaking change for CS6.

@JimPanic
Copy link
Contributor

We will not be able to keep up with ES201x without introducing breaking changes into CS, I think that is quite certain.

This is not inherently a bad thing. A lot of CS code that is out there right now might still work, but the ecosystem has changed and continues to change quite rapidly. I see a lot of former must-have libraries being replaced by the standard library and ES201x language features; just like with CS before.

@carlsmith
Copy link

On a technical level, if we fixed classes, we would have everything we need. Everything else can be added to CoffeeScript without breaking anything, or isn't required for interop with JavaScript. It's just a nice to have. As long as CoffeeScript has a good set of features in its own right, and can continue to use the entire JavaScript ecosystem, it can continue as its own language, with its own destructuring features. There's no fundamental reason why CoffeeScript needs the same feature set as ES6 (or syntax).

On a pragmatic level, CoffeeScript still needs a lot of features it could otherwise live without, just to stem the exodus to ES6, and semicolons.

I'm personally backing a novel approach, where we define domain specific JavaScript dialects for each project, adding features to the dialect as you go along. I have a working compiler, but there's lots left to do, so not much point going into details, but it works, and it makes adding features much easier than using macros, and a lot more efficient.

Once you trivialise writing parsers, and target Babel, there's no reason why users need to pick a language, and deal with the compromises. They can just pick a small, core dialect, then add features to it, as they need them. All the common features will already be implemented, so they would literally just select what they want from a list of features that is pretty much a superset of every altJS language. If you need something a bit different, there's an API that is still easier to use than macros.

Sorry. I didn't mean to plug my library. It's not even out yet. I just wanted to say that it is possible to trivialise parsing (without resorting to clunky parser generators), and is a better approach long term than creating six hundred similar languages, each with its own benefits, and requiring each project to pick one of them.

@rattrayalex
Copy link
Contributor

@carlsmith sounds interesting. Do you have a repo you can share?

@carlsmith
Copy link

I do have it online here, just for backup, but the code is really sketchy at the moment. I'm still figuring some things out, and then I'll tidy everything up.

You can probably figure out how to use it from looking at the code at the bottom of the file. If you do have a look and have any questions, just open an issue on that repo mate.

I think it was your idea @rattrayalex to target Babel. That was a really good idea. Thanks.

@rattrayalex
Copy link
Contributor

Wow looks quite interesting. Looking forward to following along on the development @carlsmith

@Asc2011
Copy link
Author

Asc2011 commented Aug 24, 2016

@carlsmith just to make sure i understand your concept in 'shalt' :

  • CS-core will be CS(1.10) plus ES6-classes and ES6-modules
  • all future language-additions will be seperate and don't require a contributor to work on the CS-codebase

and in effect, the community-/core-developers make sure that

  • no addition breaks/conflicts with CS-core
  • conflicts between additions remain in the responsponsibillity of the respective authors and users
  • users/consumers decide on using additions by rolling their own CS-compiler - alike rollup.js
  • all published contributions remain under the patronage of either Classic-CS or this project

I believe this to be a strong concept :) It's truly novel and en-vogue - looking at D3js-V4. It could become a game-changer. As it simplifies decisions and seems truly liberal. I welcome such a solution in every way.

The discussion about it should continue on #25 .

@carlsmith
Copy link

carlsmith commented Aug 24, 2016

@Asc2011 - Thanks man, and you totally get the concept, but my library doesn't parse CoffeeScript. Sorry - I should have made that clearer. It parses custom dialects of a language similar to JavaScript. Most of the features are up to the user, but I hardcoded the grammar for primitives and whitespace, and used Brendan Eich's Paren Free Mode.

Whitespace

There's no Automatic Semicolon Insertion. Implicit terminators are based on significant newlines, like in Python, so you can omit semicolons safely. The logic is consistent for statements, and expressions, so you can omit trailing commas according to the precise same logic as you can omit semicolons.

array = [
    foo, bar
    spam, eggs
]

if x > y {
    do spam
    do eggs
}

That also gets rid of the git-blame problem, without allowing trailing commas.

Indentation and trailing whitespace (outside of string literals) are totally insignificant.

Paren Free

In all the predefined grammar, parens around predicates are optional, but blocks must be braced, even if they contain a single statement. The parser assumes you'll do your dialect this way, so it's essentially required, if you want an easy life.

if foo { do spam } else { do eggs }

while foo > bar {
    // do something here...
}

It works the same with functions and generators too:

square = function x { return x * x }

counter = generator {
    i = 0
    loop { yield i++ }
}

These examples use the grammar I would opt for, but you may prefer something different. It's only the primitive literals, whitespace and Paren-Free that you're basically stuck with (and wrapping expressions in parens to create an expression group, but who would ever change that anyway??).

Sorry for a long, off topic reply. Just thought people seem interested enough, and I don't want to disappoint anyone when it turns out it's not a CoffeeScript parser.

It's really just a general purpose altJS parser, but I figured, if we're transpiling to JS, I may as well take a rare opportunity make JavaScript clean and simple, but wanted to avoid really adding anything. Innovation can happen around the library.

Again, the source is well sketchy. Please don't jump to any conclusions based on it. I'm trying to work out the best API before tightening any bolts too much.

@rattrayalex
Copy link
Contributor

rattrayalex commented Aug 24, 2016

This is definitely awesome stuff, but also definitely the wrong thread for it 😄

Let's open a new one and move these comments there? Personally I think it's 👍 to chat about coffee-cousins on this repo, and it might be valuable to @carlsmith to be able to gather feedback and share ideas here.

(sidenote, pardon the hypocrisy: here's the link to Brendan Eich's "Paren Free Mode" post for the lazy – and this post by Douglas Crockford seems to be another source of inspiration behind Shalt and is quite interesting).

EDIT: to clarify, I actually think #25 might not be the right place for this thread to move, since @carlsmith doesn't expect his tool to be used for CSNext directly.

@carlsmith
Copy link

Thanks @rattrayalex. Appreciate it. Sounds good. We could move that discussion to the shalt repo, as I'll eventually use that once the code is ready, but it would be nice to keep things on this repo, closer to where the discussion is taking place too. Hmm.

I'll could open an issue for it here, once it's a bit further along, or anyone can as soon as they want to discuss it really.

@GeoffreyBooth
Copy link
Collaborator

Getting back to destructuring assignment, what exactly is the ask here? CoffeeScript already has a feature it calls destructuring assignment; is it missing something that ES2015’s version of destructuring assignment provides?

If CoffeeScript’s version is missing something, then it sounds like this is a feature request—some new syntax that outputs ES2015’s syntax, so that we get whatever missing feature ES2015 added.

If the features are functionally equivalent, then the request seems to be just that CoffeeScript output the ES2015 syntax for simplicity and readability’s sake; similar to transpiling => to =>, which is satisfying and makes debugging easier but ultimately doesn’t add any new “feature” to CoffeeScript.

Nothing against the latter, but I want to understand which it is so that we can prioritize. Missing features should take priority over improving output.

@lydell
Copy link

lydell commented Sep 6, 2016

@GeoffreyBooth the only thing I know that ES destructuring can do but CS destructuring can't is plucking values from a generator:

function* countToFive() {
  let i = 1
  while (i <= 5) {
    yield i
    i++
  }
}

const counter = countToFive()
const [a, b, c, d, e, f, g] = counter
console.log('results:', a, b, c, d, e, f, g)
//> results: 1 2 3 4 5 undefined undefined

However, that's not because of CoffeeScript's syntax, it's because of what CoffeeScript compiles to. Outputting ES2015+ would solve that. (But requires [@a] = b to compile to something like var [tmp] = b; this.a = tmp;.)

@rattrayalex
Copy link
Contributor

Closing as this has been marked as "no action" in https://github.com/coffeescript6/discuss/blob/master/Features.md

I'm personally not opposed to re-opening in the future.

@rattrayalex
Copy link
Contributor

Given the long-running confusion around what exactly is being asked for here (I know I personally misinterpreted), I suggest that any ask for related features occur in a new thread.

Any comments clarifying the purpose here would certainly be welcome to occur on this thread.

@coffeescriptbot coffeescriptbot changed the title Destructuring assignment CS2 Discussion: Output: Destructuring assignment Feb 19, 2018
@coffeescriptbot
Copy link
Collaborator

Migrated to jashkenas/coffeescript#4919

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

8 participants