How to define the basic mathematical operations for structs in Rust?

## Define Vector struct and create an instance of it

We can defined a 2 dimensional vector by the two coordinates it points to:

```
struct Vector {
x: i32,
y: i32,
}
```

We can then create an instance of this Vector:

```
let a = Vector {
x: 2,
y: 3,
};
```

## Print the struct - derive from Debug

We cannot print the Vector using this `println!("a: {}",a);`

as `Display`

is not implemented by default.

We cannot even use the debugging print `println!("a: {:?}",a);`

because `Debug`

is not implemented by default.

We can implement both by ourselves, but it is easier to just `derive`

the `Debug`

trait. So for this we'll have

```
#[derive(Debug)]
struct Vector {
x: i32,
y: i32,
}
```

and then we can use

```
println!("a: {:?}",a);
```

or

```
dbg!(&a);
```

However, Rust will complain that we have not used the `x`

and `y`

attributes of the vector. In real code we will probably access those and we won't need to silence this warning, but
here we do. So let's allow for dead code using `#[allow(dead_code)]`

:

```
#[derive(Debug)]
#[allow(dead_code)]
struct Vector {
x: i32,
y: i32,
}
```

We can use the debugging printing in three different ways:

```
println!("a: {:?}",a);
println!("a: {a:?}");
dbg!(&a);
```

## Adding two structs together

Given two vectors:

```
let a = Vector {
x: 2,
y: 3,
};
let b = Vector {
x: 4,
y: 5,
};
```

We can try to add them together:

```
let c = a + b;
```

This won't compile as Rust does not know how to add two arbitrary structs together. Rust will complain: **must implement Add**.

No need to worry, we can implement the Add trait.

```
impl Add for Vector {
type Output = Self;
fn add(self, other: Self) -> Self {
Self {
x: self.x + other.x,
y: self.y + other.y,
}
}
}
```

The lowercase `self`

will be the variable that is on the left-hand-side of the operation and the `other`

will be on the right-hand-side.
This `other`

is expected to be the `Vector`

type which is represented here by `Self`

(with capital S).

The add function returns a value of the same type (again using `Self`

the generic name instead of the specific `Vector`

,

Now we can have:

```
let c = a + b;
println!("c: {c:?}");
```

## Multiply two structs

In the case of these vectors multiplying one such vector by another vector does not make much sense so I won't implement it.

We can have another example where we implement matrix-multiplication on them, but this isn't that article.

## Multiply a struct with a number

This seemed to make more sense. The idea here is to multiply each coordinate by the same number.

We would like to be able to write code like this, where on the left-hand-side of the operator there is a `Vector`

and the right-hand-side is an `i32`

number.

```
let d = c * 2;
println!("d: {d:?}");
```

For this to work we need to implement the Mul trait:

```
impl Mul<i32> for Vector {
type Output = Self;
fn mul(self, rhs: i32) -> Self::Output {
Self { x: self.x * rhs, y: self.y * rhs }
}
}
```

However this will only allow `c * 2`

it won't handle the `2 * c`

case. For that we need to implement that too:

Instead of duplicating all the "calculation", this implementation swaps the two operands and make the code reuse the above implementation.

```
impl Mul<Vector> for i32 {
type Output = Vector;
fn mul(self, rhs: Vector) -> Self::Output {
rhs * self
}
}
```

## Full example

**examples/2d-vectors/src/main.rs**

```
use std::ops::Add;
use std::ops::Mul;
#[derive(Debug)]
#[allow(dead_code)]
struct Vector {
x: i32,
y: i32,
}
impl Add for Vector {
type Output = Self;
fn add(self, other: Self) -> Self {
Self {
x: self.x + other.x,
y: self.y + other.y,
}
}
}
impl Mul<i32> for Vector {
type Output = Self;
fn mul(self, rhs: i32) -> Self::Output {
Self {
x: self.x * rhs,
y: self.y * rhs,
}
}
}
impl Mul<Vector> for i32 {
type Output = Vector;
fn mul(self, rhs: Vector) -> Self::Output {
rhs * self
}
}
fn main() {
let a = Vector { x: 2, y: 3 };
let b = Vector { x: 4, y: 5 };
// We need to derive from Debug to make this printable
println!("a: {:?}", a);
println!("b: {b:?}");
dbg!(&a);
// We need to implement the [Add trait](https://doc.rust-lang.org/std/ops/trait.Add.html)
let c = a + b;
println!("c: {c:?}");
// // We need to implement the [Mul trait](https://doc.rust-lang.org/std/ops/trait.Mul.html)
let d = c * 2;
println!("d: {d:?}");
let e = 2 * d;
println!("e: {e:?}");
}
```

## Output

```
a: Vector { x: 2, y: 3 }
b: Vector { x: 4, y: 5 }
[src/main.rs:55:5] &a = Vector {
x: 2,
y: 3,
}
c: Vector { x: 6, y: 8 }
d: Vector { x: 12, y: 16 }
e: Vector { x: 24, y: 32 }
```