Skip to content

Conversation

@zdenko
Copy link
Collaborator

@zdenko zdenko commented Feb 3, 2018

Fixes #4878.

eqJS '''
foo = (list) ->
[first, ..., last] = list
''', '''
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let’s please avoid eqJS tests whenever possible, they break unnecessarily with minor updates to the output. You could instead use:

fn = (list) ->
  [first, ..., last] = list
  [first, last]

arrayEq [3, 5], fn([3, 4, 5])

and so on.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This example would compile on master.
This PR fixes the issue where destructuring is the last line.

foo = (list) ->
  [ first, ..., last ] = list

But, anyway, you're right. I'll change the tests.

src/nodes.coffee Outdated
isSplat = splats.length
isExpans = expans.length
isSplat = splats.length > 0
isExpans = expans.length > 0
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could splats or expans possibly be undefined? This seems safer (and slightly more performant):

isSplat = splats?.length isnt 0
isExpans = expans?.length isnt 0

f4 = (list) ->
([first, ...rest] = list); rest

arrayEq f1(arr), ['d']
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In 2.1.1, f1(arr) returns [ 'a', 'b', 'c', 'd' ]

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In 2.1.1 this

f1 = (list) ->
 [first, ..., last] = list

compiles into

f1 = function(list) {
  var first, last;
  return first = list[0], last = list[list.length - 1], list;
};

So, the returned value is list.

In 2.2.0 it's compiled to

f1 = function(list) {
  var first, last;
  return [first] = list, [last] = slice.call(list, -1);
};

The returned value is `[last]'.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, but [first, ..., last] = list is shorthand for return [first, ..., last] = list, which looks to me like it should return the full array. As in, returning just [last] is wrong.

do -> [a, b, c] = [1, 2, 3]
# returns [1, 2, 3]

Copy link
Collaborator Author

@zdenko zdenko Feb 3, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yup. Sorry, my mistake. Not enough coffee in the system 😪

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not enough coffee in the system

Isn’t that why you’re here? 😝


foo = (list) ->
ret =
if list.length
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don’t like using list.length being nonzero as a proxy for truthiness. If you’re evaluating that list.length isnt 0, you should be explicit about it. I think it’s a lot more readable than just list.length or other hacks like !!.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right. I copied the example from #4878.

@zdenko
Copy link
Collaborator Author

zdenko commented Feb 3, 2018

@GeoffreyBooth the last commit fixes the returned value, but I just found another issue, which I'll fix later today.
Sorry, I was too quick with the push.

@GeoffreyBooth
Copy link
Collaborator

No worries.

The tests we have at least prove that this syntax compiles; it would be nice to also somehow prove that first and last are the values we expect them to be.

@zdenko
Copy link
Collaborator Author

zdenko commented Feb 3, 2018

@GeoffreyBooth the “issue” I noticed before is a false alarm.
When I checked this compiled output,

foo = (list) ->
  ret =
    if list.length > 0
      [first, ..., last] = list
      [first, last]
    else
      []
foo = function(list) {
  var first, last, ret;
  return ret = list.length > 0 ? (([first] = list, [last] = slice.call(list, -1), list), [first, last]) : [];
};

I thought that this part (([first] = list, [last] = slice.call(list, -1), list) shouldn’t include list at the end.
Although it’s not a bug, since the returned value is correct, it would be nicer if it could be omitted from such expressions.
It’s probably a task for some other PR.

@GeoffreyBooth GeoffreyBooth merged commit 794f65f into jashkenas:master Feb 3, 2018
Copy link
Collaborator

@GeoffreyBooth GeoffreyBooth left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approved

@GeoffreyBooth GeoffreyBooth mentioned this pull request Feb 5, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants