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

Add Iterator::intersperse #79479

Merged
merged 2 commits into from
Dec 31, 2020
Merged

Add Iterator::intersperse #79479

merged 2 commits into from
Dec 31, 2020

Conversation

camelid
Copy link
Member

@camelid camelid commented Nov 27, 2020

This is a rebase of #75784. I'm hoping to push this past the finish line!

cc @jonas-schievink

@camelid camelid added A-iterators Area: Iterators T-libs-api Relevant to the library API team, which will review and decide on the PR/issue. labels Nov 27, 2020
@rust-highfive
Copy link
Collaborator

r? @joshtriplett

(rust-highfive has picked a reviewer for you, use r? to override)

@rust-highfive rust-highfive added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Nov 27, 2020
@camelid camelid force-pushed the intersperse branch 2 times, most recently from 67fd81c to b2f144f Compare November 27, 2020 22:51
@camelid
Copy link
Member Author

camelid commented Nov 27, 2020

Squashed.

@camelid camelid force-pushed the intersperse branch 2 times, most recently from 1ddd660 to ee18244 Compare November 27, 2020 23:00
@camelid
Copy link
Member Author

camelid commented Nov 27, 2020

r? @LukasKalbertodt (you're the original reviewer, feel free to re-assign)

@camelid

This comment has been minimized.

@LukasKalbertodt

This comment has been minimized.

@m-ou-se
Copy link
Member

m-ou-se commented Nov 28, 2020

r? @m-ou-se

@lukaslueg
Copy link
Contributor

lukaslueg commented Nov 28, 2020

Two cents: We could lift the I::Item: Clone bound by providing a method to the tune of Iterator::intersperse_with(seperator_gen: impl Fn() -> Self::Item). That way, we can do intersperse_with(|| Ok(1)), without requiring that Result<T, E> to be Clone, removing the Clone-bound from Intersperse. Only Iterator::intersperse has a bound then and becomes a shorthand which clones the given value over and over again internally.


Having thought about it again, I think we'd need a separate Iterator::intersperse_with() -> IntersperseWith, as Iterator::intersperse would have to need a return type akin to Intersperse<Self, impl FnMut -> Self::Item>, which we can't do in trait implementations as of now. Since intersperse.rs is small, the duplication wouldn't hurt. iter::Repeat and ::RepeatWith are precedent. Poke me for a PR if there is interest.

@CraftSpider
Copy link
Contributor

CraftSpider commented Nov 29, 2020

What would the opinion be on making it support fn intersperse<T: Into<Self::Item>>(self, separator: T)? (Please tell me if this would better go in the tracking issue/zulip)

@m-ou-se
Copy link
Member

m-ou-se commented Nov 29, 2020

The signature for this function is a good question. Since it only clones the separator, a reference to it would suffice. However, that'd make it a bit more complicated in usage, as it'd always be borrowing something, making it a bit tricky with the lifetime in some situations.

The most flexible signature would be that of intersperse_with (which I believe is added in itertools 0.10). If we also have that function, then intersperse itself is simply a more specific version of that function, just for one common case. So in that case, I'd be less worried about picking the perfect/most flexible signature for intersperse. With intersperse_with as the generic/flexible alternative, it makes sense for intersperse to just be the simplest version. It'd also avoid some breakage if it has the exact same signature as in itertools.

@lukaslueg
Copy link
Contributor

I don't want to derail this, as there has already been quite some discussion before in #75784 and related. To reiterate, I just think the Clone-bound is quite harsh for the general case and especially iterators that do not iterate over immutable references. An intersperse_with would lift this restriction and also address #79479 (comment), as the closure can do the required conversion without complicating the signature of intersperse_with (akin Into). Afaics, an implementation of intersperse can't reuse the machinery of intersperse_with, as we'd have to generate a closure which does the cloning and becomes part of the return type, which we can't do in a trait. However, there is precedent in Repeat and RepeatWith for exactly this kind of situation.

To the tune of

Iterator::intersperse_with<G>(self, separator_gen: G) -> IntersperseWith<Self, G> where Self:Sized, G: FnMut() -> Self::Item
Iterator::intersperse(self, separator: Self::Item) -> Intersperse<Self> where Self:Sized, Self::Item: Clone

@camelid
Copy link
Member Author

camelid commented Nov 29, 2020

Since it only clones the separator, a reference to it would suffice. However, that'd make it a bit more complicated in usage, as it'd always be borrowing something, making it a bit tricky with the lifetime in some situations.

Could we use Borrow<Self::Item> instead?

@lukaslueg
Copy link
Contributor

Borrow is more strict than AsRef and AsRef<Self::Item> probably suffices. However, I'd suggest not to have a generic parameter on intersperse in case we can have intersperse_with, because indirection can be done there, and intersperse's signature remains as simple and straightforward as possible.

@camelid
Copy link
Member Author

camelid commented Nov 29, 2020

I haven't added a function to libs before, so I'm fine with whatever is agreed upon as long as it's reasonable :)

@lukaslueg
Copy link
Contributor

Imho the intersperse as it is now - with minimal signature - has merits; I didn't want to derail this PR, as extensive discussion seems to have taken place. I'd take a look at implementing intersperse_with as mentioned above to accommodate more elaborate use-cases (like Borrow/Into), unless @camelid wants to.

@lukaslueg
Copy link
Contributor

@m-ou-se love poke

@m-ou-se
Copy link
Member

m-ou-se commented Dec 30, 2020

Sorry for the delay. This looks good to me. r=me with the merge conflict resolved.


One comment: Should Intersperse implement FusedIterator if the underlying iterator implements it? (This can be added later, so doesn't need to be resolved now.)

@m-ou-se
Copy link
Member

m-ou-se commented Dec 30, 2020

I'd take a look at implementing intersperse_with as mentioned above

Nice, I'd love to see a PR for that. :)

@m-ou-se m-ou-se added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Dec 30, 2020
@camelid
Copy link
Member Author

camelid commented Dec 30, 2020

One comment: Should Intersperse implement FusedIterator if the underlying iterator implements it? (This can be added later, so doesn't need to be resolved now.)

That seems reasonable. Like you said, though, we can always add it later. I'll defer to you :)

@camelid camelid added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. and removed S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. labels Dec 30, 2020
@m-ou-se
Copy link
Member

m-ou-se commented Dec 30, 2020

@bors r+

@bors
Copy link
Contributor

bors commented Dec 30, 2020

📌 Commit 40bbb7f has been approved by m-ou-se

@bors bors added S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Dec 30, 2020
bors added a commit to rust-lang-ci/rust that referenced this pull request Dec 30, 2020
Rollup of 9 pull requests

Successful merges:

 - rust-lang#78934 (refactor: removing library/alloc/src/vec/mod.rs ignore-tidy-filelength)
 - rust-lang#79479 (Add `Iterator::intersperse`)
 - rust-lang#80128 (Edit rustc_ast::ast::FieldPat docs)
 - rust-lang#80424 (Don't give an error when creating a file for the first time)
 - rust-lang#80458 (Some Promotion Refactoring)
 - rust-lang#80488 (Do not create dangling &T in Weak<T>::drop)
 - rust-lang#80491 (Miri: make size/align_of_val work for dangling raw ptrs)
 - rust-lang#80495 (Rename kw::Invalid -> kw::Empty)
 - rust-lang#80513 (Add regression test for rust-lang#80062)

Failed merges:

r? `@ghost`
`@rustbot` modify labels: rollup
@bors bors merged commit 9cf2438 into rust-lang:master Dec 31, 2020
@rustbot rustbot added this to the 1.51.0 milestone Dec 31, 2020
@camelid camelid deleted the intersperse branch December 31, 2020 00:23
@pickfire
Copy link
Contributor

Should there be a doc alias to join since it is similar?

m-ou-se added a commit to m-ou-se/rust that referenced this pull request Jan 14, 2021
Add Iterator::intersperse_with

This is a follow-up to rust-lang#79479, tracking in rust-lang#79524, as discussed rust-lang#79479 (comment).

~~Note that I had to manually implement `Clone` and `Debug` because `derive` insists on placing a `Clone`-bound on the struct-definition, which is too narrow. There is a long-standing issue # for this somewhere around here :-)~~

Also, note that I refactored the guts of `Intersperse` into private functions and re-used them in `IntersperseWith`, so I also went light on duplicating all the tests.

If this is suitable to be merged, the tracking issue should be updated, since it only mentions `intersperse`.

Happy New Year!

r? `@m-ou-se`
m-ou-se added a commit to m-ou-se/rust that referenced this pull request Jan 14, 2021
Add Iterator::intersperse_with

This is a follow-up to rust-lang#79479, tracking in rust-lang#79524, as discussed rust-lang#79479 (comment).

~~Note that I had to manually implement `Clone` and `Debug` because `derive` insists on placing a `Clone`-bound on the struct-definition, which is too narrow. There is a long-standing issue # for this somewhere around here :-)~~

Also, note that I refactored the guts of `Intersperse` into private functions and re-used them in `IntersperseWith`, so I also went light on duplicating all the tests.

If this is suitable to be merged, the tracking issue should be updated, since it only mentions `intersperse`.

Happy New Year!

r? ``@m-ou-se``
@tesuji tesuji mentioned this pull request Jan 18, 2021
m-ou-se added a commit to m-ou-se/rust that referenced this pull request Jan 20, 2021
m-ou-se added a commit to m-ou-se/rust that referenced this pull request Jan 20, 2021
bors added a commit to rust-lang-ci/rust that referenced this pull request Jan 21, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-iterators Area: Iterators S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. T-libs-api Relevant to the library API team, which will review and decide on the PR/issue.
Projects
None yet
Development

Successfully merging this pull request may close these issues.