-
Notifications
You must be signed in to change notification settings - Fork 12.7k
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
Add Iterator::flatten #48115
Add Iterator::flatten #48115
Conversation
Thanks for the pull request, and welcome! The Rust team is excited to review your changes, and you should hear from @dtolnay (or someone else) soon. If any changes to this PR are deemed necessary, please add them as extra commits. This ensures that the reviewer can see what has changed since they last reviewed the code. Due to the way GitHub handles out-of-date commits, this should also make it reasonably obvious what issues have or haven't been addressed. Large or tricky changes may require several passes of review and changes. Please see the contribution instructions for more information. |
You should use a new-type because it affords us more wiggle-room /wrt what we need to keep stable. With a regular
and would prohibit us from changing what FlatMap<_> is. |
One of my original ideas was to use a newtype, exactly with your rationale, but on the other hand, users may now have to Is there a particular reason you think we'd change the data definition of |
One reason to use a newtype instead could be to get rid of the type parameter With a type alias, we can't do anything with the On the other hand... having one parameter means that we can't There seems to be good reasons to go with either a type alias or newtype - so for me it is a toss up / draw right now... |
No new struct would be awesome for the code reuse benefits you have mentioned, but still, we'd prefer to have each of I would like to boldly skip the much-unused double ended case in the flatten iterator (like Itertools does), but that creates an inconsistency that I guess is not so popular(?) |
@bluss One newtype coming Right Up™ =) On the |
/// .map(|s| s.chars()) | ||
/// .flatten() | ||
/// .collect(); | ||
/// assert_eq!(merged, "alphabetagamma"); |
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.
It's worth mentioning that this is equivalent to flat_map. (And that flat_map is preferable in this case?)
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.
Sure, why not =) Can't hurt.
So... I ran into a problem... If we want to have one type parameter on pub struct Flatten<I: Iterator>
where I::Item: IntoIterator {
iter: I,
frontiter: Option<<I::Item as IntoIterator>::IntoIter>,
backiter: Option<<I::Item as IntoIterator>::IntoIter>,
} instead of: pub struct Flatten<I, U> {
iter: I,
frontiter: Option<U>,
backiter: Option<U>,
} unfortunately, this implies that the struct definition of pub struct FlatMap<I, U: IntoIterator, F>
where I: Iterator, F: FnMut(I::Item) -> U {
iter: Flatten<Map<I, F>>,
} instead of: pub struct FlatMap<I, U: IntoIterator, F> {
iter: Flatten<Map<I, F>, U>,
} but now we have imposed two additional conditions upon This I think leaves us with two viable paths to take:
Here's my experiment... Dumping it for future reference: https://play.rust-lang.org/?gist=3cfcc5742a7fbdcaea163381f7c72951&version=nightly My preference would be to go with option 2. but I am very much open to suggestions. |
I discussed this further with @eddyb, and I think the best way forward is to have I'll fix this up in a bit =) |
Refactored according to recent discussion and added requested docs by @theotherphil. |
Looks good to me, thanks @Centril! Want to open an issue for tracking the instability here and we can r+? |
@alexcrichton Done =) Tracking issue is #48213. |
@bors: r+ Thanks! |
📌 Commit 1291432 has been approved by |
a8c93db
to
819d57a
Compare
Should be up to snuff now. |
@bors: r+ |
📌 Commit 819d57a has been approved by |
🌲 The tree is currently closed for pull requests below priority 100, this pull request will be tested once the tree is reopened |
…=alexcrichton Add Iterator::flatten This adds the trait method `.flatten()` on `Iterator` which flattens one level of nesting from an iterator or (into)iterators. The method `.flat_fmap(f)` is then redefined as `.map(f).flatten()`. The implementation of `Flatten` is essentially that of what it was for `FlatMap` but removing the call to `f` at various places. Hopefully the type alias approach should be OK as was indicated / alluded to by @bluss and @eddyb in rust-lang/rfcs#2306 (comment). cc @scottmcm
@CryZe Christopher, I just ran into this issue with itertools, did indeed break my builds on nightly. Annoying, but I am not sure what would have been the best direction here. |
This should‘ve at least been a crater run and required some more discussion imo. Even without stabilization, this will break stable in 2 cycles. |
I agree, it would have been nice to at least have better data and maybe a
discussion on this.
…On Feb 26, 2018 3:12 PM, "Christopher Serr" ***@***.***> wrote:
This should‘ve at least been a crater run and required some more
discussion imo. Even without stabilization, this will break stable in 2
cycles.
—
You are receiving this because you commented.
Reply to this email directly, view it on GitHub
<#48115 (comment)>, or mute
the thread
<https://github.com/notifications/unsubscribe-auth/AAABxABUkgPl_Mt1iRb7xK8uj1YSLZ8Wks5tYmdbgaJpZM4SA1Bh>
.
|
I'm sorry that I didn't investigate the impact of the itertools compatibility issue before this feature was merged. The explanation for that is simply that this is a day that I have been expecting, when There are two ways to work around compatibility problems, mentioned in this itertools PR: rust-itertools/itertools#266, including a free function called |
Lower the priority of unstable methods when picking a candidate. Previously, when searching for the impl of a method, we do not consider the stability of the impl. This leads to lots of insta-inference-regressions due to method ambiguity when a popular name is chosen. This has happened multiple times in Rust's history e.g. * `f64::from_bits` #40470 * `Ord::{min, max}` #42496 * `Ord::clamp` #44095 (eventually got reverted due to these breakages) * `Iterator::flatten` #48115 (recently added) This PR changes the probing order so that unstable items are considered last. If a stable item is found, the unstable items will not be considered (but a future-incompatible warning will still be emitted), thus allowing stable code continue to function without using qualified names. Once the unstable feature is stabilized, the ambiguity error will still be emitted, but the user can also use newly stable std methods, while the current situation is that downstream user is forced to update the code without any immediate benefit. (I hope that we could bring back `Ord::clamp` if this PR is merged.)
Tracking issue: #48213
This adds the trait method
.flatten()
onIterator
which flattens one level of nesting from an iterator or (into)iterators. The method.flat_fmap(f)
is then redefined as.map(f).flatten()
. The implementation ofFlatten
is essentially that of what it was forFlatMap
but removing the call tof
at various places.Hopefully the type alias approach should be OK as was indicated / alluded to by @bluss and @eddyb in rust-lang/rfcs#2306 (comment).
cc @scottmcm