Add Iterator::intersperse by camelid · Pull Request #79479 · rust-lang/rust (original) (raw)

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 andprivacy statement. We’ll occasionally send you account related emails.

Already on GitHub?Sign in to your account

Conversation21 Commits2 Checks0 Files changed

Conversation

This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.Learn more about bidirectional Unicode characters

[ Show hidden characters]({{ revealButtonHref }})

camelid

@rust-highfive

r? @joshtriplett

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

@camelid

@camelid

@camelid

This comment has been minimized.

@LukasKalbertodt

This comment has been minimized.

@m-ou-se

@lukaslueg

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

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

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

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

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

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

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

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

@m-ou-se

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

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

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

@bors

📌 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

@bors

@pickfire

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

@m-ou-se

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

@m-ou-se

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 20, 2021

@m-ou-se

m-ou-se added a commit to m-ou-se/rust that referenced this pull request

Jan 20, 2021

@m-ou-se

bors added a commit to rust-lang-ci/rust that referenced this pull request

Jan 21, 2021

@bors

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.