qed
qed

Reputation: 23104

Choose to borrow or pass ownership without duplicating code in Rust

I wish I could choose to pass a ref or the thing itself without having to write the same function several times, like this:

use std::ops::Add;

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

pub trait Add1<RHS=Self> {
    type Output;
    fn add1(&self, rhs: &RHS) -> Self::Output;
}



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

impl Add1 for Point {
    type Output = Point;
    fn add1(&self, other: &Point) -> Point {
        Point { x: self.x + other.x, y: self.y + other.y }
    }
}

fn main() {
    let p1 = Point { x: 1, y: 0 };
    let p2 = Point { x: 2, y: 3 };
    let p4 = p1.add1(&p2);
    let p3 = p1 + p2;
    println!("{:?}", p3);
    println!("{:?}", p4);
}

How can avoid this kind of redundancy?

Upvotes: 2

Views: 100

Answers (2)

Tibor Benke
Tibor Benke

Reputation: 1280

What if you implement Add for &Point?

use std::ops::Add;

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

impl Add for Point {
    type Output = Point;
    fn add(self, other: Point) -> Point {
        println!("refadd");
        Point { x: self.x + other.x, y: self.y + other.y }
    }
}

impl<'a> Add for &'a Point {
    type Output = Point;
    fn add(self, other: &Point) -> Point {
        Point { x: self.x + other.x, y: self.y + other.y }
    }
}

fn main() {
    let p1 = Point { x: 1, y: 0 };
    let p2 = Point { x: 2, y: 3 };
    let p4 = &p1 + &p2;
    let p3 = p1 + p2;
    println!("{:?}", p3);
    println!("{:?}", p4);
}

Upvotes: 0

malbarbo
malbarbo

Reputation: 11177

You can use Borrow to abstract over the borrowed type

use std::ops::Add;
use std::borrow::Borrow;

#[derive(Clone, Debug)]
struct Point {
    x: i32,
    y: i32,
}

impl<T: Borrow<Point>> Add<T> for Point {
    type Output = Point;
    fn add(self, other: T) -> Point {
        Point { x: self.x + other.borrow().x, y: self.y + other.borrow().y }
    }
}

fn main() {
    let p1 = Point { x: 1, y: 0 };
    let p2 = Point { x: 2, y: 3 };
    let p4 = p1.clone() + &p2;
    let p3 = p1 + p2;
    println!("{:?}", p3);
    println!("{:?}", p4);
}

Upvotes: 4

Related Questions