-
Notifications
You must be signed in to change notification settings - Fork 328
is_first/is_last to ease handling of Position::Only #1042
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
Conversation
Theoretically, it would also be possible to implement |
Good Observation, but I am pretty Sure that Related: #1019 @jswrenn thoughts? |
Renaming the enum variants may help draw the attention to the footgun, but it doesn't improve its poor ergonomics (still requiring two comparisons with even more verbose variant names). I would prefer not to make an incompatible change, because IMHO But if you're going to change it in an incompatible way, just stop using pub struct Position {
pub first: bool,
pub last: bool,
} and you can add |
You might consider instead writing
@phimuemue I agree, and I think it'd complement quite well with
A core part of this crate's mission is to serve as a laboratory for iterator adaptors before they're uplifted into the standard library. We're keen to fiddle with ergonomics and willing to make breaking changes because once an adaptor is uplifted to std, that luxury vanishes. In this case, we can ease the pain the of break by re-exporting deprecated aliases for these variants. |
Hmm, I wonder if expression the 4 variants as 2x2 could be a way to address this? Like suppose instead of returning Then you get (Hopefully someone else can come up with a better naming for those enums, though. I think different types are better than just |
Riffing off @scottmcm's proposal, perhaps we should define #[derive(Copy, Clone)]
struct Position {
pub is_last: bool,
pub is_first: bool,
}
impl Position {
pub fn is_middle(&self) -> bool {
!self.is_first && !self.is_last
}
pub fn is_only(&self) -> bool {
self.is_first && self.is_last
}
} This would be amenable to pattern matching and still allow us to define helpful predicates on |
My usecase looks like this (using all elements, but treating the last specially) for (pos, widget) in widgets {
…
if !pos.is_last() { separator(); }
} (in that case the code is imperative, and the items don't have the same type, so Destructuring from a wrapper struct would not be useful for me. It makes it harder to name the variable:
(and I keep forgetting is it and adding some
but that's still worse than a tuple. for (_, widget, is_last) in widgets {
…
if is_last == IsLast::No { separator(); }
} This is tolerable, but having a |
In my proposal, your use-case would be written as: for (pos, widget) in widgets {
…
if !pos.is_last { separator(); }
} There's no need to destructure. |
Let's do this. It (hopefully) draws the attention to the fact that Shold we make I'm still thinking if we should rename to |
@kornelski Just for completeness, because I had similar situations: I almost always end up with one of |
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## master #1042 +/- ##
==========================================
- Coverage 94.38% 94.12% -0.27%
==========================================
Files 48 50 +2
Lines 6665 6249 -416
==========================================
- Hits 6291 5882 -409
+ Misses 374 367 -7 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
I've updated the code to what's been discussed here. CI needs #1044 |
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.
Thank you.
@jswrenn I'd be fine with that. So if you don't object, we can merge this.
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.
Thank you.
041c733
I wanted to handle the last (final) element of an iterator differently, and used
if position == Position::Last {…}
, which turned out to be a bug-causing gotcha, becausePosition::Only
is also an element after which there are no more elements left.Having to write
position == Position::Last || position == Position::Only
makes this a bit verbose.I've changed
Position
to be a struct to make it easier to check the conditions separately. This is a semver-major change.