【发布时间】:2018-09-04 09:42:32
【问题描述】:
所以我一直在尝试实现一个向量和矩阵数学库,并且我创建了一些可以正常工作但想要概括所有数字基元并将功能添加到普通运算符的函数。
我的想法是为Vec<T> 创建一个容器,该容器可以包含数字类型(如i32)或Vec 的另一个容器,以便尽可能使用矩阵。尔格:
#[derive(Clone, Debug)]
struct Mat<T>(Vec<T>);
然后,将两个任意数量的 vecs 相加,我实现 Add as:
impl<'a, T> Add for &'a Mat<T>
where T: PartialEq + PartialOrd + Add<T> + Sub<T> + Mul<T> + Div<T> + Rem<T> + Clone {
type Output = Option<Mat<<T as std::ops::Add>::Output>>;
fn add(self, other: &Mat<T>) -> Self::Output {
let a: &Vec<T> = self.pop();
let b: &Vec<T> = other.pop();
match a.len() == b.len() {
true => {
let mut retvec: Vec<<T as std::ops::Add>::Output> = Vec::new();
for i in 0..a.len() {
retvec.push(a[i].clone() + b[i].clone());
}
Some(Mat(retvec))
},
false => None
}
}
}
编辑:为了进一步澄清,Mat::pop() 只是 unwrap 函数,尽管名称可能很糟糕。
将任意数量的两个向量相加的基本方案似乎可行。
#[test]
fn add_override_vectors() {
let vec: Mat<i32> = Mat(vec![2, 2, 2]);
let newvec = &vec + &vec;
assert_eq!(*newvec.unwrap().pop(), vec![4,4,4]);
}
但是矩阵让我很头疼。对他们来说,add 函数看起来非常相似,除了 let Some(x) 语句:
impl<'a, T> Add for &'a Mat<Mat<T>>
where T: Add<&'a Mat<T>>{
type Output = Option<Mat<T>>;
fn add(self, other: &Mat<Mat<T>>) -> Self::Output {
let a: &Vec<Mat<T>> = self.pop();
let b: &Vec<Mat<T>> = other.pop();
match a.len() == b.len() {
true => {
let mut retvec: Vec<T> = Vec::new();
for i in 0..a.len() {
if let Some(x) = &a[i] + &b[i] {
retvec.push(x);
}
}
Some(Mat(retvec))
},
false => None
}
}
}
我得到的错误信息是:
error[E0369]: binary operation `+` cannot be applied to type `&Mat<T>`
--> src\main.rs:46:38
|
46 | if let Some(x) = &a[i] + &b[i] {
| ^^^^^^^^^^^^^
|
= note: an implementation of `std::ops::Add` might be missing for `&Mat<T>`
所以编译器说Add 可能不会为&Mat<T> 实现,但我认为我已经指定了边界,以便它在where T: Add<&'a Mat<T> 中具有该要求。在我看来,&a[i] 中的任何内容似乎都应该实现 Add trait。我在这里做错了什么?
作为额外的澄清,我的想法是Add for &'a Mat<Mat<T>> 应该能够被递归调用,直到它归结为Vec,其中包含一个实际的数字类型。然后应该调用Add for &'a Mat<T>。
【问题讨论】:
-
嗯,我想我看错了。您的意思是在实现内部的某处将
T添加到Mat<T>吗?这就是T: for<'b> Add<&'b Mat<T>>所暗示的。我怀疑你实际上想要for<'b> &'b Mat<T>: Add(但这会导致更多问题) -
我不确定我是否得到了您的要求,如果您的意思是我忘记为
T和Mat<T>实现 Add 函数,那么我认为我不会需要一个,因为 forloop 循环遍历两个函数中的两个向量,它只需要添加T + T或Mat<T> + Mat<T>,对吗?否则,如果你的意思是如果我尝试做T + Mat<T>,那么不,我发布的测试是我迄今为止唯一的测试。 -
您的
where子句适用于T + &Mat<T>,但您在函数内部实际执行的是&Mat<T> + &Mat<T>(我认为)。但这还不是全部,因为修复绑定会导致其他问题。 -
我认为,你想要的是
&a[i] + &b[i],而不是a[i].clone() + b[i].clone()
标签: matrix vector rust traits bounds