为什么在比较变量时需要取消引用变量而不是在算术时取消引用?

geo*_*rch 3 operators rust

我有以下代码:

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;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

为什么我需要prime在第二个条件(*prime > limit)中取消引用,当我不需要在第一个条件()中这样做时number % prime == 0

这两个%<是两个数字并把返回一些运营商.唯一的区别似乎在于它们返回的内容(数字与布尔值).虽然为什么不能将借用的整数与文字整数进行比较? 确实解释了使代码工作所需的内容(所有重载的实现,理想情况下在标准库中),它没有说明它为什么起作用a % b.这些运营商之间是否存在根本区别?或者它还没有实现?

Sve*_*ach 5

比较运算符实际上的行为与算术运算符不同.在查看特征定义时,差异变得明显.举个例子,这就是PartialEq特质

pub trait PartialEq<Rhs = Self>
where
    Rhs: ?Sized,
{
    fn eq(&self, other: &Rhs) -> bool;
    fn ne(&self, other: &Rhs) -> bool { ... }
}
Run Code Online (Sandbox Code Playgroud)

Add特点

pub trait Add<RHS = Self> {
    type Output;
    fn add(self, rhs: RHS) -> Self::Output;
}
Run Code Online (Sandbox Code Playgroud)

我们可以看到比较特征通过引用获取操作数,而算术特征通过值获取操作数.这种差异反映在编译器如何转换运算符表达式中:

a == b   ==>   std::cmp::PartialEq::eq(&a, &b)
a + b    ==>   std::ops::Add::add(a, b)
Run Code Online (Sandbox Code Playgroud)

比较的操作数被评估为位置表达式,因此它们永远不会移动值.另一方面,算术运算符的操作数被计算为值表达式,因此根据操作数类型是否移动或复制它们Copy.

由于这种差异的结果,如果我们实行PartialEq的类型A,我们不仅可以比较AA,但也&A&A凭借DEREF的强制的操作数.对于Add在另一方面,我们需要一个单独的实施能够添加&A&A.

我无法回答为什么标准库实现"混合"版本以供算术运算符的引用和值,但不能用于比较.我看不出后者无法完成的根本原因.