0

I want to define a method on the struct that can take both owned and borrowed references of parameters and perform an operation. To achieve this I am repeating the same function six times, to implement it for each pair of owned and borrowed reference as shown below:

Suppose I have a struct called Vector defined as:

#[derive(Debug, PartialEq)]
pub struct Vector {
    pub elements: Array<f64, ndarray::Dim<[usize; 1]>>,
}

Now I want to implement multiplication operator on this struct. Currently, I have achieved it like this, where I repeat the same code for each pair of Owner and Borrower six times:

impl Mul<Vector> for f64 {
    type Output = Vector;
    fn mul(self, vector: Vector) -> Vector {
        Vector::new(Array::from_vec(vector.elements.iter().map(|x| x * self).collect::<Vec<f64>>()))
    }
}

impl Mul<&Vector> for f64 {
    type Output = Vector;
    fn mul(self, vector: &Vector) -> Vector {
        Vector::new(Array::from_vec(vector.elements.iter().map(|x| x * self).collect::<Vec<f64>>()))
    }
}

impl Mul<&Vector> for &f64 {
    type Output = Vector;
    fn mul(self, vector: &Vector) -> Vector {
        Vector::new(Array::from_vec(vector.elements.iter().map(|x| x * self).collect::<Vec<f64>>()))
    }
}


impl Mul<f64> for Vector {
    type Output = Vector;
    fn mul(self, scalar: f64) -> Vector {  
    Vector::new(Array::from_vec(self.elements.iter().map(|x| x * scalar).collect::<Vec<f64>>()))
    }
}

impl Mul<f64> for &Vector {
    type Output = Vector;
    fn mul(self, scalar: f64) -> Vector {  
    Vector::new(Array::from_vec(self.elements.iter().map(|x| x * scalar).collect::<Vec<f64>>()))
    }
}

impl Mul<&f64> for &Vector {
    type Output = Vector;
    fn mul(self, scalar: &f64) -> Vector {  
    Vector::new(Array::from_vec(self.elements.iter().map(|x| x * scalar).collect::<Vec<f64>>()))
    }
}

1 Answers1

1
  1. Why do you even want this? Do you really want to be able to multiply a vector by a reference to a float? If you have:
let vector: Vector;
let num: &f64;

Why not simply dereference num (or vector) like this?

let multiplied = vector * (*num);
  1. I general T and &T are different types in Rust. So you don't really have other choice than to have a separate implementation for each combination (that is if you want to support all combinations, which I think you shouldn't).

  2. But you can define one implementation in the terms of the other. For example:

impl Mul<f64> for Vector {
    type Output = Vector;
    fn mul(self, scalar: f64) -> Vector {  
        Vector::new(Array::from_vec(
            self.elements.iter()
                .map(|x| x * scalar)
                .collect::<Vec<f64>>()
        ))
    }
}

impl Mul<&f64> for Vector {
    type Output = Vector;
    fn mul(self, scalar: &f64) -> Vector {  
        vector * (*scalar)
    }
}
Aleksander Krauze
  • 3,115
  • 7
  • 18