I really want there to be a function to get both x / y
and x % y
at once in the standard library. Some reasons that I think this is justified as something to put in std
:
-
This is a very commonly used function, for integers in particular. Think of indexing into multidimensional arrays (and similar regular data structures), splitting a work queue into fixed-size chunks (with some tasks left over), and tons of domain-specific tasks (budgeting, unit conversion, number theory, whatever).
-
It is trivial to implement for the primitive types, and cleaner for the user.
-
This is present in standard libraries for many different languages, such that many new users might expect it to be there.
-
It would be sad if several crates implemented slightly different versions of this.
So, here’s the trait that I was thinking of implementing (and a little test):
use std::ops::{Div,Rem};
trait DivRem<RHS = Self>: Div<RHS> + Rem<RHS> {
fn div_rem(self, rhs: RHS)
-> (<Self as Div<RHS>>::Output, <Self as Rem<RHS>>::Output);
}
impl DivRem for isize {
fn div_rem(self, rhs: isize) -> (isize, isize) {
let quotient = self / rhs;
(quotient, self - (quotient*rhs))
}
}
fn main() {
println!("(+/+) {:?}", 9is.div_rem(8));
println!("(+/-) {:?}", 9is.div_rem(-8));
println!("(-/+) {:?}", (-9is).div_rem(8));
println!("(-/-) {:?}", (-9is).div_rem(-8));
}
Output is of course:
(+/+) (1i, 1i)
(+/-) (-1i, 1i)
(-/+) (-1i, -1i)
(-/-) (1i, -1i)
Simple as this is, I know there’s always room for bikeshedding, (plus, discussion is educational for me) so here’s my justification for various decisions:
-
I didn’t add this to existing traits like
Int
orFloat
, partly because those types are much more specific than I need, but mostly because I hoped that making a new trait would avoid backwards compatibility issues. If I can avoid trying to force an RFC through while 1.0 is still somewhat in flux, I would greatly prefer to leave the core team to more urgent matters like io/os stabilization. -
The method is
div_rem
instead ofdivmod
because this is more consistent with Rust’s names and conventions, and I thought that that was the most important consideration. I do know that more people would recognize (and search for)divmod
, however. Using the worddivmod
in the documentation might help with this. -
There’s no blanket implementation because we don’t have specialization, and an efficient
impl
is half the point. There’s no default implementation, because otherwise we would needCopy
orClone
bounds, and I didn’t think it would be worth it. -
I didn’t use an associated type for the result because I felt like it was determined by the trait bounds and didn’t need to be specified by
impl
s.
One sort-of unresolved question for me: it seems like this makes more sense in std::num
than std::ops
. But it’s only tied to the ops
trait definitions. (Also, I’ve kind of wished that languages had a dedicated operator for this, but I don’t especially expect that to happen in Rust.)