< 返回版块

johnmave126 发表于 2021-02-22 10:56

Tags:proc_macro

repo: symm_impl

之前看到社区里的一个帖提问如何实现两个不同类型的对称操作,比如圆和矩形是否相交(即圆和矩形是否相交等价于矩形和园是否相交)。由于我是做计算几何的,想到确实几何种这种算符很多,比如距离算符,集合交并算符,都满足不同类型实现对称运算符的问题。

于是就花了点时间写了个attribute macro,用于在实现了一边的情况下,自动实现对称的版本。

以点和圆的距离作为例子

use symm_impl::symmetric;

trait Distance<Other> {
    fn distance(&self, other: &Other) -> f64;
}
struct Point2D {
    x: f64,
    y: f64,
}
struct Disk {
    center: Point2D,
    radius: f64
}
impl Distance<Point2D> for Point2D {
    fn distance(&self, other: &Point2D) -> f64 {
        let dx = self.x - other.x;
        let dy = self.y - other.y;
        (dx * dx + dy * dy).sqrt()
    }
}
#[symmetric]
impl Distance<Disk> for Point2D {
    fn distance(&self, other: &Disk) -> f64 {
        let p_diff = self.distance(&other.center);
        if p_diff.le(&other.radius) {
            0.0_f64
        } else {
            p_diff - other.radius
        }
    }
}
/* Expands to
impl Distance<Point2D> for Disk {
    #[allow(unused_mut)]
    #[inline]
    fn distance(&self, other: &Point2D) -> f64 {
        <Point2D as Distance>::distance(other, self)
    }
}
*/

fn main() {
    let p = Point2D { x: 5.0, y: 4.0 };
    let c = Disk {
        center: Point2D { x: 1.0, y: -2.0 },
        radius: 3.0,
    };
    assert_eq!(p.distance(&c), c.distance(&p));
}

Ext Link: https://github.com/johnmave126/symm_impl

评论区

写评论
eweca-d 2021-02-22 14:23

star了。有点意思啊,其实rust官方真该出一个类似的宏作为语法糖进标准库,因为实际上很多操作普遍满足交换律。

1 共 1 条评论, 1 页