-
Notifications
You must be signed in to change notification settings - Fork 12.9k
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::checked_{sum, product}
#95485
Add Iterator::checked_{sum, product}
#95485
Conversation
r? @scottmcm (rust-highfive has picked a reviewer for you, use r? to override) |
This isn't something I feel comfortable approving without extra @rust-lang/libs-api oversight. The code is perfectly fine, but I don't know if
So that means |
My 2c as my code was cited as the inspiration for this:
I think the general problem here is that there aren't any abstractions for checked arithmetic whatsoever. There's not a I know there have been various proposals for those, however the API surface for those is comparatively large. This seems like something small which could provide a lot of utility for checked arithmetic users. For anyone trying to write code which disallows
The reason I added RustCrypto/formats#558 was I found myself writing a slightly more verbose form of the code above often enough (across many types which are performing checked length computations) that I wanted something with less verbosity and more semantic clarity.
I would really love
I think I just read a pretty interesting C++-focused blog post about whether should saturating be a function, a type, or both and my personal reaction to it was while Perhaps there are use cases I'm not familiar with, though. |
Would you be interested in trialing this in your codebase and providing feedback about the experience? I don't want to start spreading FUD because I've not participated much in the threads around these wrapper types, and what I have seen I only remember poorly, but I recall there being usability issues with some of these wrappers. Hopefully someone else on the team remembers what I'm alluding to and can link the threads in question but if not it would probably be worth digging through the history for |
@yaahc this PR actually implements a pattern I was already using organically: RustCrypto/formats#558 Regarding a The main drawback is having every method be fallible and using |
I don't think the issue was |
Yeah, I think the reason something like That's why I'm somewhat excited by this PR in comparison: the API surface and implementation are small, and speaking from experience I think the ergonomics are fantastic and far superior to any other approach I've tried, especially for the multi-field-checked-length-calculation use case. I think there's merit to solving the same problem with a Really I'd be happy with either approach. |
That's certainly true in core, but one can always use https://docs.rs/num-traits/latest/num_traits/ops/checked/trait.CheckedAdd.html#tymethod.checked_add and friends if needed. For example, you could toss together something like fn checked_sum<T: CheckedAdd + Zero>(a: impl AsRef<[T]>) -> Option<T> {
a.as_ref().iter().try_fold(T::zero(), |a, b| a.checked_add(b))
} Those traits would also let you write the extension trait in your own code as just one thing (rather than one per type), calling the Or on the far-off horizon, it could be variadic instead of taking an array/slice.
There's what I would consider a fairly substantial succinctness difference between them, because yours is on Indeed, for optimal succinctness it'd be something like this (which doesn't even need num-traits): macro_rules! checked_sum {
( $first:expr $(, $rest:expr )* $(,)? ) => {
[$($rest),*].into_iter().try_fold($first, |a, b| a.checked_add(b))
}
} Or in your code it could have a much shorter name, since checked is so much more common.
I think that pushes me even more in the "it feels weird that it's on Iterator then" direction. One thing it reminds me of is that core's simd now has Now, you don't want to use that specifically (it only works for power-of-two length right now, it's not checked, and simd in most chips is actually pretty bad at cross-lane reductions like this) but it makes me wonder if some of these things existing on arrays too (not just simd) might be reasonable.
Literals are definitely a pain today. But someone's looking at them and got |
I think my preference would be for
where the second implies adding Doing this by composing the existing generic The docs of |
This was discussed in this week's libs-api meeting. The takeaway was to not add this,
So I'm going to close this specific PR, following that. However, there was some interest in having something that could do it through |
745: Do not sum options r=phimuemue a=Philippe-Cholet A mistake on my part, discovered in time as code is still commented out. Note that it passed tests. It only returns None if the iterator yields None. But it would overflow whenever an addition does. Do not product options either, as multiplications could overflow the same way. That's how I found out. I guess `checked_sum` and `checked_product` methods would be nice. EDIT: ~Would you be interested?~ Related: rust-lang/rust#95485 Co-authored-by: Philippe-Cholet <phcholet@orange.fr>
Adds a checked version of
sum
andproduct
to iterators,Based on RustCrypto/formats#558 cc @tarcieri
Docs:
Tracking issue: #95484