-
Notifications
You must be signed in to change notification settings - Fork 2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Implement #156, Added expansion to destructuring #3268
Conversation
It seems to me the elision should be represented by |
I'm pretty sure we decided against this in #870, opting to recommend |
@michaelficarra you mean Also note that |
@davidchambers I used @michaelficarra @lydell You are correct, but the compiled code is still inefficient: [first, []..., last] = a # first = a[0], 3 <= a.length ? __slice.call(a, 1, _i = a.length - 1) : (_i = 1, []), last = a[_i++];
#vs
[first, .., last] = a # first = a[0], last = [a.length - 1] We could open up an issue for the compilation and fix it, but imho this syntax is utterly ugly and non-intuitive. Mind that #870 did not offer the change as a solution to #156. @jashkenas ? |
Seems to me that splat should work here, without the need for |
@Nami-Doc Because splat never stands on its own, it always serves as either assignment target or application. (a, splat...) -> # splat is assigned
fn splat... # splat is applied
[.., last] = a # do not assign the values until the last one
# "stretch the empty space" or "shift the assigned index towards end" I think this should be completely disallowed, see the nonsensical output: [[]...] = a # var __slice = [].slice; 1 <= a.length ? __slice.call(a, 0) : []; I see how splats make sense coming from that syntax, but I think given no one actually knows it, it doesn't make the syntax more intuitive. But if that's the only problem stopping us, happy to go for one more dot. |
@xixixao there's actually a problem with your proposed "efficient" compilation here. What happens when a = ['first']
[first, .., last] = a # first = a[0], last = [a.length - 1]
first # => 'first'
last # => 'first' Even crazier hypothetical case: a = []
[first, ..., last] = a
first # => undefined
last # => ??? OK, in this case, |
@erisdiscord I don't think the second is a problem: a = []
a[-1] = 'I am a devil'
last = a[a.length - 1] # well, that really isn't our fault |
I have more time now again, so I could finish this up. Do we want this? @Nami-Doc ? |
@@ -1236,12 +1237,21 @@ exports.Assign = class Assign extends Base | |||
val += ") : []" | |||
val = new Literal val | |||
splat = "#{ivar}++" | |||
else if not expansion and obj instanceof Expansion |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
maybe we should check here for multiple expansions. Minor nitpick though ...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I just copied the way Splats are handled. Would you change both? (I don't remember whether there's a reason for the deferral of the error to the last block).
I still believe |
I like this, because the current way is just a hack. Compare the following two: [first, []..., last] = array
# Destructure `array`. Save its first value into `first`. Soak up the second til the next-to-last
# value (if any) into an array, but don't save it to a variable. Instead, immediately
# destructure that array. However, don't save any of its values to any variable. Which is like
# skipping to the last value of the initial array. Save that value to `last`. Phew! [first, .., last] = array
# Desctructure `array`. Save its first value in `first`. Skip to the last value. Save that value to
# `last`. Done. Moreover, it provides a solution to that old "I wish As for |
My vote would be for three dots. In my head, three dots is "ellipsis/splat/soak", and two dots is "go back a level". |
@xixixao because of POSIX paths I'd assume |
@xixixao: @erisdiscord is correct. Ever since my very first Unix login long ago, ".." has been burned into my brain as the way to go up the directory tree. |
Ah, I even had In CS, two dots currently have two meanings: |
My thoughts: If y'all want this, it should definitely be three dots instead of two — an ellipsis is a real thing. And it should work as a standalone token in any reasonable circumstance. That means the here-suggested:
... as well as things like this:
... and so on. Another thing to think about, syntactically, is the strangeness / ugliness of an ellipsis followed by a comma, or preceded by one:
Just a notion. |
I think that notation is pretty natural, at least in a mathematical context. For example, take a look at some of the sequences mentioned in the Wikipedia article for sequence:
😺 |
[first, second...butOne, last] = a
[first, second, ..., butOne, last] = a Latter reads better for me. Secondly, as I mentioned, it would be really hard to parse if it coincided with ranges. |
Agreed, I'd really prefer if we kept the comma mandatory |
Ok. Sounds good. Is it ready to merge, then? |
@@ -1206,7 +1206,7 @@ exports.Assign = class Assign extends Base | |||
vvar = value.compileToFragments o, LEVEL_LIST | |||
vvarText = fragmentsToText vvar | |||
assigns = [] | |||
splat = false | |||
expandedIdx = false |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if we can't keep the align, we probably should keep only one space
@jashkenas If it works with argument lists as you said, I'd say yes (once the sigil is fixed). Glad to see that in |
Ready to squash @Nami-Doc ? |
if p.this then p = p.properties[0].name | ||
if p.value then o.scope.add p.value, 'var', yes | ||
splats = new Assign new Value(new Arr(p.asReference o for p in @params)), | ||
new Value new Literal 'arguments' | ||
break | ||
for param in @params | ||
debugger |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
whoops ;)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ha :)
Now should be ready. |
Implement #156, Added expansion to destructuring
What are we going to do about the single-argument-skipping syntax? Just yesterday I had to use this ugly hack: [[], commit, timestamp, author] = stdout.match /([A-F\d]{40}) (\d+) ([^@\s]+@[^@\s]+)/i |
Just name it? |
Gross. That makes it look like you mean to use it later, and will cause linting tools to (perfectly legitimately) complain about an unused variable. |
I agree that is ugly, and in future I'd like to make Btw I had a similar case as Michael's above when writing the new error logic in coffee-script.coffee. |
Feel free to go ahead, I might get to it later but 1.7.0 is a priority now. |
Implements #156 (oldest open issue currently). Namely @epidemian's proposal (same as #870).
This matches nicely the ability of taking first
n
elements out of an array.edited to match final PR