Skip to content
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

Allow a specified depth for flatten #2460

Merged
merged 2 commits into from
Jul 28, 2020

Conversation

paulfalgout
Copy link
Contributor

Per a new TC39 proposal http://bterlson.github.io/proposal-flatMap/#sec-Array.prototype.flatten they're suggesting a depth argument.

This was fairly trivial to implement without breaking the current functionality.

Thoughts?

Per a new TC39 proposal http://bterlson.github.io/proposal-flatMap/#sec-Array.prototype.flatten they're suggesting a depth argument.

This was fairly trivial to implement without breaking the current functionality.

Thoughts?
@akre54
Copy link
Collaborator

akre54 commented Mar 7, 2016

Awesome. 👍

@megawac
Copy link
Collaborator

megawac commented Mar 7, 2016

👍

_.flatten = function(array, shallow) {
return flatten(array, shallow, false);
_.flatten = function(array, depth) {
if (!depth) depth = Infinity;
Copy link
Contributor

Choose a reason for hiding this comment

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

Should a depth of 0 be seen as Infinity?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

so you think we need a if (depth === 0) return array; ?

Copy link
Collaborator

Choose a reason for hiding this comment

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

👍

Copy link
Contributor

Choose a reason for hiding this comment

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

Should return a shallow clone/slice which should shake out naturally if 0 is allowed to be used as a depth (no need for a if or special branch)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

so then if (!depth && depth !== 0) return

Copy link
Contributor

Choose a reason for hiding this comment

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

@paulfalgout To preserve as much back compat ya I think that would do.

@paulfalgout
Copy link
Contributor Author

So looking into both 0 and negative values, it seems much cleaner to handle this in _.flatten than it would be to try to get the internal flatten to play nice with these additional scenarios, particularly related to the "strict" argument. I also assumed that negative would act the same as 0?

@jdalton
Copy link
Contributor

jdalton commented Mar 7, 2016

it seems much cleaner to handle this in _.flatten than it would be to try to get the internal flatten to play nice with these additional scenarios

Oh cool!

I also assumed that negative would act the same as 0

Yeah.

} else if (depth <= 0) {
return _.clone(array);
}
return flatten(array, depth, false);
Copy link
Collaborator

Choose a reason for hiding this comment

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

Might want to ToNumber depth here so we're not passing true to flatten.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

we're internally calling flatten with booleans, so I don't know if we want to enforce that at the moment?

Copy link
Collaborator

Choose a reason for hiding this comment

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

can we updat ethe internal calls to use a number

@michaelficarra
Copy link
Collaborator

LGTM 👍

_.flatten = function(array, shallow) {
return flatten(array, shallow, false);
_.flatten = function(array, depth) {
if (!depth && depth !== 0) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

This conditional confuses the hell out of me. Maybe:

if (depth === false) {
  depth = Infinity;
} else if (depth === true) {
  depth = 1;
} else if (depth < 0) {
  depth = 0;
}

Copy link
Contributor Author

Choose a reason for hiding this comment

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

the internal flatten doesn't handle depth 0 at all and will conflict with whatever "strict" is doing.
depth as with shallow is optional so the default value is Infinity, but to keep with the current API false should also be assumed as Infinity so I suppose it could be:

if(depth === false || _.isUndefined(depth)) {
  depth = Infinity;
} else if (depth <= 0) {
  return _.clone(array);
}

We can certainly add the else if (depth === true) { but flatten is called internally with true elsewhere.

@paulfalgout
Copy link
Contributor Author

This was initially easy, but got complicated with edge cases and without refactoring internals a bit.
Any ideas what we should do with this PR? I've answered the two outstanding questions, but I'm not certain they're resolved.

Copy link
Collaborator

@jgonggrijp jgonggrijp left a comment

Choose a reason for hiding this comment

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

@paulfalgout I think you already did the right thing. I think this is not even a breaking change. I'm in favor of merging this, but it has gotten a bit out of sync and I just opened #2849 which will make this even more out of sync. So let's postpone merging this just a little bit more.

Really good job!

@jgonggrijp
Copy link
Collaborator

@paulfalgout I merged #2849 three weeks ago and I nearly forgot to get back to you. Sorry about that.

So master should be stable again for a while and I see no reason not to finish your PR. With some luck, we should be able to include it in the upcoming 1.11 release. In order to do so, we need to update your patch first. Please let me know whether you'd like to do this yourself, or whether you'd prefer me to take care of these final steps:

  1. Check out the feature branch and pull in the latest changes from master. Disregard the merge conflict for now and postpone the merge commit until step 5.
  2. Run a fresh npm install to update all the tools and install our commit hooks. These will take care of updating the underscore.js.
  3. Update modules/_flatten.js and modules/flatten.js (note the underscore) with the changes that you originally made in the old underscore.js.
  4. Run git add underscore.js to silence the warnings about the merge conflict. The conflict markers will be overwritten by the pre-commit hook.
  5. Commit and push.

@jgonggrijp
Copy link
Collaborator

I'm now looking into merging this by executing the above steps myself. On closer inspection, I noticed that many internal calls to flatten use the internal flatten with a boolean. I think I'll address this by moving the guard that changes false into Infinity from the public to the internal flatten.

@paulfalgout
Copy link
Contributor Author

@jgonggrijp thanks for hopping on this.. I've been a little out of it as of late.

@jgonggrijp
Copy link
Collaborator

Welcome.

@jgonggrijp jgonggrijp merged commit b2221eb into jashkenas:master Jul 28, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants