I have the following code:
fn example(known_primes: &[i32], number: i32, prime: i32, limit: i32) {
let mut is_prime = true;
for prime in known_primes {
if number % prime == 0 {
is_prime = false;
break;
}
if *prime > limit {
break;
}
}
}
Why do I need to dereference prime
in the second condition (*prime > limit
), when I don't need to do so in the first one (number % prime == 0
)?
Both %
and <
are operators that take two numbers and return something. The only difference seems to be in what they return (a number vs. a boolean). While Why isn't it possible to compare a borrowed integer to a literal integer? does explain what would be required to make the code work (implementations for all overloads, ideally in the standard library), it does not say why it does work for a % b
. Is there a fundamental difference between these operators? Or is it just not implemented yet?
Comparison operators actually do behave differently than arithmetic operators. The difference becomes obvious when looking at the trait definitions. As an example, here is the PartialEq
trait
pub trait PartialEq<Rhs = Self>
where
Rhs: ?Sized,
{
fn eq(&self, other: &Rhs) -> bool;
fn ne(&self, other: &Rhs) -> bool { ... }
}
and the Add
trait
pub trait Add<RHS = Self> {
type Output;
fn add(self, rhs: RHS) -> Self::Output;
}
We can see that comparison traits take the operands by reference, while the arithmetic traits take the operands by value. This difference is reflected in how the compiler translates operator expressions:
a == b ==> std::cmp::PartialEq::eq(&a, &b)
a + b ==> std::ops::Add::add(a, b)
The operands of comparisons are evaluated as place expressions, so they can never move values. Operands of arithmetic operators, on the other hand, are evaluated as value expressions, so they are moved or copied depending on whether the operand type is Copy
.
As a result of this difference, if we implement PartialEq
for the type A
, we can not only compare A
and A
, but also &A
and &A
by virtue of deref coercions for the operands. For Add
on the other hand we need a separate implementation to be able to add &A
and &A
.
I can't answer why the standard library implements the "mixed" versions for reference and value for arithmetic operators, but not for comparisons. I can't see a fundamental reason why the latter can't be done.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With