-
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
Tracking issue for Iterator::flatten #48213
Comments
A flatten could be useful, but I think there are more important/useful functions/iterators to add before a flatten. |
@leonardo-m Clearly not important enough for someone to write a PR/RFC before this one, though. ;) |
Also I can't list the number of times I've done One thing that I think should be clarified is that this only flattens one level, i.e. it will not transform |
@leonardo-m I don't think it has to be an either-or proposition - if there are more useful additions, and there certainly are some from Itertools, they should be made irrespective of this one. Someone just has to write the PRs for those =) Regarding @clarcharr hmm, it does say in the docs that:
Perhaps that's not clear enough? Can we fix this during stabilization perhaps if it is not? |
@Centril I mentioned that having not actually read the docs yet. ;) I honestly think that including an example would be clearer; there are tools for languages such as JavaScript, for example, which will completely flatten an array regardless of how many levels it has. Although such a thing would be very difficult and/or impossible to do with Rust's type system, I think it'd be best for it to be clear that this is not a "deep" flatten, just a shallow one. |
@clarcharr Updated the docs with your example. |
Awesome! Thanks |
Not sure, how important this angle is, but just in case -- it looks like this introduces a failure for nightly builds on code that relies on itertools' version of flatten: https://it.sit-it.org/issue/fe5e68e5-22a1-4bc3-8ebf-36586460ba27 It's a trivial fix for the code that uses it (the patch is in the first link) but I thought it is worth mentioning this aspect. |
``` --> sit-web/src/webapp.rs:202:32 | 202 | let record = match sit_core::repository::IssueRecordIter::flatten(issue.record_iter().unwrap()).find(|r| r.encoded_hash() == record) { | ^^^^^^^ multiple `flatten` found | = note: candidate #1 is defined in an impl of the trait `std::iter::Iterator` for the type `sit_core::repository::IssueRecordIter<'_>` = note: candidate #2 is defined in an impl of the trait `itertools::Itertools` for the type `_` = note: candidate #3 is defined in the trait `rayon::iter::ParallelIterator` ``` This is, perhaps, related to the addition of the [`iterator_flatten` nightly feature](rust-lang/rust#48213). Solution: use itertools' version explicitly
I don't think arbitrary-level flattening is impossible with Rust's type system, it's just that it would rely on specialisation and could produce confusing results. For example, Also, this would cause an infinite loop in the compiler when resolving the output type of struct Foo;
impl Iterator for Foo {
type Item = Foo;
fn next(&mut self) -> Foo {
unimplemented!()
}
} JS is dynamically typed and so deep flattening is useful since you don't know the nesting level until runtime. With Rust you know ahead of time precisely how many levels deep an iterator will be nested. |
Perhaps mention that this is more useful with scan instead of map? https://bitbucket.org/SoniEx2/wcc-rs/src/e07c866224a84accda05fa7fd4d956a185daabf7/src/lib.rs?at=master&fileviewer=file-view-default#lib.rs-147:157 |
@SoniEx2 I think the documentation has a sufficient number of examples, more would be too many. |
I don't agree. So far in my whole codebase I have seen zero places where to use a flatten(), on the other hand from the standard library I miss several iterable things already present in itertools. The API of the std library should be kept small. Adding functions is not free, the more things you add, the more time you need to use the API and find the right function. In my opinion the whole business of adding iterators to the Rust std library is currently broken. It should be based on real data. What are the most used iterators of the itertools crate? Add those to the std library. |
I have written scan+flat_map(|x|x) at least 3 times so far. And I don't even use Rust that often yet! The more I use rust, the more I run into scan+flatten. See also: rust-lang/rfcs#1978 It's most useful for string parsing, and partial collects. |
@SimonSapin This has been in nightly for a few months now; could we stabilize? |
We may want another (check-only) crater run before stabilizing due to conflict with |
Perhaps |
In either case, whether it is possible or not, I don't think a nested flatten operation should be called |
I've been thinking about this issue for a while, and i came up with something, but sadly i don't currently have the time to try a full implementation, so I'll write down a sketch of it, maybe it makes some sense (If it does I'll invest a few hours into learning how to properly contribute over the weekend). Basically, have a trait |
I did some experimentation: https://play.rust-lang.org/?gist=1bbdca273415c488e2f058d39fe995b2&version=nightly&mode=debug |
@reuvenpo That sounds maybe plausible with specialization of a trait that has an associated type (for the returned iterator). But the design of the trait specialization feature itself in the language is still evolving, so it might be a long time before "deep flatten" is possible at all. In the mean time, the existing |
…<try> Stabilize Iterator::flatten in 1.29, fixes #48213. This PR stabilizes [`Iterator::flatten`](https://doc.rust-lang.org/nightly/std/iter/trait.Iterator.html#method.flatten) in *version 1.29* (1.28 goes to beta in 10 days, I don't think there's enough time to land it in that time, but let's see...). Tracking issue is: #48213. cc @bluss re. itertools. r? @SimonSapin ping @pietroalbini -- let's do a crater run when this passes CI :)
Would it be appropriate to open a tracking issue for Or should an RFC be made first? |
Generally it's considered bad practice to have the behaviour rely on specialisation (rather than specialisation being an optimisation) because it means that In JavaScript the |
@Vurich, i'll start by addressing the second part of your message, and then elaborate on it, hopefully answering the first part too. It's true that in dynamically typed languages this is useful because both the author and the language may not know the depth of nesting for a given object, but it doesn't necessarily mean that in a statically typed language the author would like to care about the level of nesting of a given object, in some contexts. My example would be anything resembling a tree structure with unbounded depth (For example a directory structure). It may be desirable to have a function generalizes over In this context, say you had a function that received a structure whose concrete type was something like The type information is all there, it's just impossible to use currently, for these purposes. It would be best if you couldn't call Under this system, Of course, this is all pretty difficult, if at all possible, to implement today. I certainly don't know the "right" way to do this, if it was possible, I just think this interface makes sense and is doable, even if it still requires some features that aren't yet stabilized, or available at all. P.S. Obviously for cases where the concrete type is known, one can just call EDIT 1: changed |
"unnestable" is weird for a trait name. it sounds like you can't put it inside stuff. |
The name is just a proposal too. It can be called anything else that makes sense. ( |
The design where you specify the iterator type still fails for this: struct Foo;
impl Iterator for Foo {
type Item = Foo;
fn next(&mut self) -> Foo {
Foo
}
} |
I'm not sure i understand. (Is that even a useful pattern?) |
It would (should) do the least amount of work to return the desired result. You want an Iterator<Item=Foo>? Easy, one operation. You want an Foo? Zero operations. You want Iterator<Item=Iterator<Item=Foo>>? Also mostly easy. Etc. |
I don't see where i would use this pattern (since it prevents Foo from being an iterator over anything else, and this is a weird recursive way of doing what But again... What is the use case? Would in that use case it be useful to treat a |
Can we move discussion on flattening nested stuff to internals.rust-lang.org? |
(I'll have to open an account, but) |
…flatten, r=SimonSapin Stabilize Iterator::flatten in 1.29, fixes rust-lang#48213. This PR stabilizes [`Iterator::flatten`](https://doc.rust-lang.org/nightly/std/iter/trait.Iterator.html#method.flatten) in *version 1.29* (1.28 goes to beta in 10 days, I don't think there's enough time to land it in that time, but let's see...). Tracking issue is: rust-lang#48213. cc @bluss re. itertools. r? @SimonSapin ping @pietroalbini -- let's do a crater run when this passes CI :)
…flatten, r=SimonSapin Stabilize Iterator::flatten in 1.29, fixes rust-lang#48213. This PR stabilizes [`Iterator::flatten`](https://doc.rust-lang.org/nightly/std/iter/trait.Iterator.html#method.flatten) in *version 1.29* (1.28 goes to beta in 10 days, I don't think there's enough time to land it in that time, but let's see...). Tracking issue is: rust-lang#48213. cc @bluss re. itertools. r? @SimonSapin ping @pietroalbini -- let's do a crater run when this passes CI :)
Rollup of 7 pull requests Successful merges: - #51511 (Stabilize Iterator::flatten in 1.29, fixes #48213.) - #51853 (Fix some doc links) - #51890 (Fix inconsequential typo in GlobalAlloc doc example) - #51920 (use literal span for concrete type suggestion) - #51922 (rename the llvm-tools component to llvm-tools-preview and tweak its image) - #51936 (rename rustc's lld to rust-lld) - #51961 (Fix typo in /src/librustc_resolve/lib.rs) Failed merges: r? @ghost
…flatten, r=SimonSapin Stabilize Iterator::flatten in 1.29, fixes rust-lang#48213. This PR stabilizes [`Iterator::flatten`](https://doc.rust-lang.org/nightly/std/iter/trait.Iterator.html#method.flatten) in *version 1.29* (1.28 goes to beta in 10 days, I don't think there's enough time to land it in that time, but let's see...). Tracking issue is: rust-lang#48213. cc @bluss re. itertools. r? @SimonSapin ping @pietroalbini -- let's do a crater run when this passes CI :)
Rollup of 7 pull requests Successful merges: - #51511 (Stabilize Iterator::flatten in 1.29, fixes #48213.) - #51853 (Fix some doc links) - #51890 (Fix inconsequential typo in GlobalAlloc doc example) - #51920 (use literal span for concrete type suggestion) - #51921 (improve the error message when `#[panic_implementation]` is missing) - #51922 (rename the llvm-tools component to llvm-tools-preview and tweak its image) - #51961 (Fix typo in /src/librustc_resolve/lib.rs) Failed merges: r? @ghost
Tracking issue for #48115,
Iterator::flatten
andFlatMap
.The text was updated successfully, but these errors were encountered: