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

with_position's/Position's API improvable? #651

Closed
phimuemue opened this issue Oct 12, 2022 · 4 comments
Closed

with_position's/Position's API improvable? #651

phimuemue opened this issue Oct 12, 2022 · 4 comments

Comments

@phimuemue
Copy link
Member

phimuemue commented Oct 12, 2022

I just tried to use with_position, and realized that its Item is an enum wrapping the actual item:

pub enum Position<T> {
    First(T),
    Middle(T),
    Last(T),
    Only(T),
}

This looks ok at first glance, but it apparently impedes manipulating the wrapped value and keeping the information whether it's first, middle, last, or only: It seems you must unpack the value (via into_inner) and manually construct e.g. a Position<()> - which feels very inconvenient.

I hope I did not miss any obvious solutions (please tell me if I did), so here's two alternatives how Itertools could overcome this:

  1. Introduce Position::map that allows transforming the wrapped value (akin to Option::map).
    • Pro: Avoids API breakage.
    • Con: Seems to be a workaround./Does possibly not cover all use cases. (E.g: What if you want to clone the wrapped value and keep the original (i.e. go from Position<T> to (Position<T>, T))?)
  2. Remove T from Position and make the Item=(Position, T) so that the position itself and the wrapped value can be used independently.
    • Pro: Seems to be cleaner and more flexible.
    • Con: API breakage. (Could be mitigated by introducing another function, e.g with_position_2).

Personally, I'd vote for option 2, accepting the API breakage.

@jswrenn @scottmcm Should we change this?

@scottmcm
Copy link
Contributor

with_position_2 would make me sad.

Maybe an inherent method for Position<T> -> (Position<()>, T)? So you could always do .with_position().map(Position::into_parts) or similar for the cases where the tuple is more convenient?

I'm kinda inspired by https://docs.rs/itertools/latest/itertools/enum.MinMaxResult.html#method.into_option for this, as another method for "well, sometimes you'd rather work with it in a different form".

Could even go a step further and change Position<T> to Position<T = ()> to encourage the used-without-payload case without it being a breaking change? Dunno if that's a good idea...

@jswrenn
Copy link
Member

jswrenn commented May 9, 2023

I like your second possibility. I don't think there's any need for a with_position_2. We can do a major release for this.

We'll need to do one anyways to fix the intersperse collision.

bors bot added a commit that referenced this issue Jun 14, 2023
699: Position<Item> -> (Position, Item) r=jswrenn a=phimuemue

As suggested in #651, we could simplify `with_position`'s API by yielding `(Position, Item)` instead of `Position<Item>`.

Note: This is a breaking change.

Co-authored-by: philipp <descpl@yahoo.de>
@Philippe-Cholet
Copy link
Member

I think this should be closed, thanks to #699.

@jswrenn
Copy link
Member

jswrenn commented Sep 18, 2023

Thanks!

@jswrenn jswrenn closed this as completed Sep 18, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants