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

[docs] In the documentation of the identify function, clarify that using flatten() is probably a better idea than using filter_map #99230

Closed
wants to merge 3 commits into from

Conversation

mousetail
Copy link
Contributor

There is a odd example on the documentation for identity that seems to suggest using filter_map to flatten a array of Option<T>. However, this can be done far shorter using flatten.

The example is good to showcase how identity works but I think a clarification would be good so people don't actually use it that way.

I hope this extra note will help people decide for themselves what the best solution to this problem is.

@rustbot rustbot added the T-libs Relevant to the library team, which will review and decide on the PR/issue. label Jul 14, 2022
@rustbot
Copy link
Collaborator

rustbot commented Jul 14, 2022

Hey! It looks like you've submitted a new PR for the library teams!

If this PR contains changes to any rust-lang/rust public library APIs then please comment with @rustbot label +T-libs-api -T-libs to tag it appropriately. If this PR contains changes to any unstable APIs please edit the PR description to add a link to the relevant API Change Proposal or create one if you haven't already. If you're unsure where your change falls no worries, just leave it as is and the reviewer will take a look and make a decision to forward on if necessary.

Examples of T-libs-api changes:

  • Stabilizing library features
  • Introducing insta-stable changes such as new implementations of existing stable traits on existing stable types
  • Introducing new or changing existing unstable library APIs (excluding permanently unstable features / features without a tracking issue)
  • Changing public documentation in ways that create new stability guarantees
  • Changing observable runtime behavior of library APIs

@rust-highfive
Copy link
Collaborator

Thanks for the pull request, and welcome! The Rust team is excited to review your changes, and you should hear from @m-ou-se (or someone else) soon.

Please see the contribution instructions for more information.

@rust-highfive rust-highfive added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Jul 14, 2022
@JohnCSimon JohnCSimon added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Aug 13, 2022
@@ -93,6 +93,8 @@ pub use num::FloatToInt;
///
/// let iter = [Some(1), None, Some(3)].into_iter();
/// let filtered = iter.filter_map(identity).collect::<Vec<_>>();
/// // Equivalent, since Option is also a Iterator itself:
/// // let filtered = iter.flatten().collect::<Vec<_>>();
Copy link
Member

Choose a reason for hiding this comment

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

Option is not an Iterator, but it does implement IntoIterator, which is sufficient for flatten().

Although flatten() is shorter to write, I personally still prefer filter_map(identity) because it is a much simpler iterator, and simple is usually better for optimization.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I hadn't really thought about the optimization aspect, just that I prefer not to import more libraries. That makes the advice previously given in the docs not as bad as I thought.

Copy link
Member

Choose a reason for hiding this comment

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

Yeah, unfortunately .flatten() is a flat_map, not a filter_map, and thus fundamentally more complex. FlatMap is bigger than FilterMap because it needs to store the prefix and suffix iterators, as those might have more elements in them, whereas because FilterMap only deals with Options so knows they can't have another item in them after getting the one value out. (You can also see this by how, for example, filter_map preserves the upper bound on a size_hint, which flat_map doesn't, though admittedly the upper bounds on size hints are useless.) And this is why https://rust-lang.github.io/rust-clippy/master/index.html#flat_map_option exists.

I see that flat_map mentions flatten in the prose, but doesn't have an example -- maybe it'd make sense to move an example like this (perhaps with arrays instead of options) over to that method?

Copy link
Member

@scottmcm scottmcm Aug 25, 2022

Choose a reason for hiding this comment

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

(Also, personally I'd never use identity here, since it needs a use and even ignoring that it isn't even shorter than writing out the |x| x closure. But since it's in the docs for identity and not for filter_map that seems fine.)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

That makes sense. Thank you for your insight, I especially appreciate including references and verifiable facts. I'll try to improve the documentation somewhere else.

I'll close this pull request.

Copy link
Member

Choose a reason for hiding this comment

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

Also, I'm glad you raised this, since it made me look for a performance lint in clippy talking about this, but instead I found exactly the opposite, a lint suggesting the .filter_map(identity) -> .flatten() change.

So I've filed rust-lang/rust-clippy#9377 for the clippy folks to discuss the situation.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-libs Relevant to the library team, which will review and decide on the PR/issue.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants