我正在尝试在Rust中实现一个基本的多项式类型,并通过重载运算符来进行数学运算。到目前为止,我已经成功地实现了加法、减法等基本运算。问题是,我希望通过引用来获取操作数,以避免不必要的复制。例如:
impl ops::Add for &Polynomial {
type Output = Polynomial;
fn add(self, other: Self) -> Polynomial {
let mut result = self.clone();
for (power, coeff) in other.coefficients.iter().enumerate() {
result.add_coeff(power, *coeff);
}
result
}
}
impl ops::Sub for &Polynomial {
// Implementation
// ...
}
impl ops::Mul for &Polynomial {
// Implementation
// ...
}
// Etc.
这种方法可以按照预期工作,但是它要求用户每次都显式地借用操作数,随着表达式变得更加复杂,代码的可读性变得降低:
let (quotient, remainder) = p2.div_rem(&p1);
assert_eq!(&("ient * &p1) + &remainder, p2);
// Even worse example found on the internet.
// Note that you need to explicitly borrow each and every intermediate result :
let result = &(&(&a * &b) + &(&c * &d)) / 2;
我认为,与其写最后两行代码,如果我可以只写以下代码,那么代码会更加简洁易读:
assert_eq!(quotient * p1 + remainder, p2);
let result = (a * b + c * d) / 2;
我希望能够让借用发生“自动化”(就像在任何值上调用具有&self
作为其第一个参数的方法时一样:它会自动且隐式地被借用,而不必显式地进行借用)。
然而,我不知道是否可能实现,或者如何实现?
Polynomial
上有+
和-
”)与实际情况(但它们不是Copy
,所以很奇怪)相冲突的情况之一。由于Rust是一种低级语言,它更倾向于实际情况的一面。 - Silvio Mayololet c = a+b;
,他们期望的是在操作之后,值a
和b
仍然可用,并且没有被消耗掉(这样你可以在同一个表达式中两次使用相同的值,比如let c = a*a;
)。但是,我不明白为什么它会排除非复制类型,如果我们可以通过引用将值传递给运算符呢?实际上,当我看到常见的运算符(比如 +、-、*、/、%)一开始并不接受引用时,我感到很惊讶,原因就是这个。 - JorString
是一个非Copy
类型,它实现了Add
,将左操作数按值传递,右操作数按引用传递。 - L. F.