0

尝试对两个数组求和 ( [1.0, 2.0] + [3.0, 4.0]) 在 Rust 中失败,因为没有为数组定义加法。我试图重载操作:

use std::ops::Add;
type float = f64;
impl<const N: usize> Add for [float;N] {
    type Output = Self;
    fn add(x : [float; N], y : [float; N]) {
        let z : [float; N];
        for i in 1..=N { z[i] = x[i] + y[i]; }
        z
    }
}

然而,现在 rustc 表示这是不允许的:“<em>只有在当前 crate 中定义的特征才能为任意类型实现”。Rust 也不允许定义自定义运算符,例如.+用于元素加法的 orso。

为什么我会想要这样的东西?我正在考虑使用 Rust 进行数值计算,已经厌倦了 Julia 的动态类型,当它无法专门化函数时,我会浪费时间试图降低隐藏的内存分配。但是,要求自定义类型和样板代码对两个数组求和似乎不太实用。对于大数组,当然想要使用其他东西;有ndarray,但基于只是试图将其包装成一般LinearOperator特征,由于缺乏AbstractArraytrait 或 enum 来涵盖具体的数组和视图,以及有些奇怪的 rhs-only 生命周期(尽管后者也可能只是我试图学习生命周期)。但是对于到处发生的简单的小而快速的“内循环”计算来说,这样的事情既不可行也不高效。另一方面,必须使用 ascii-literal 函数进行标准数学运算也无助于可读性。

有任何想法吗?未来是否有希望获得自定义(unicode)运算符或至少能够在本地重载标准运算符?(如果有人想抱怨用户可能定义了无意义的不可读运算符,我可以对按位运算符说同样的话。说真的,在 2021 年,你把它们放在语言本身中?!?)

4

1 回答 1

1

您不能为其他人的类型实现其他人的特征。这是为了防止定义冲突。如果你和我都写了一个为 vec 定义加法的板条箱,而其他人同时使用这两个板条箱怎么办?应该使用谁的实现?

您可以做的是将 vec 包装在您自己的类型中并为该类型定义 Add 。

struct MyVec<T> { 
  fn new(from: Vec<T>) { ...
}
impl Add for MyVec { ... }

如果您想使对底层 Vec 的访问透明(例如 Box Arc Mutex 等),您可以为您的类型实现 deref。

这样的事情将允许您轻松调用新类型的所有 vec 方法。

use std::ops::Deref;

struct MyVec<T> {
    value: T
}
impl<T> Deref for MyVec<T> {
    type Target = Vec<T>;

    fn deref(&self) -> &Self::Target {
        &self.value
    }
}
于 2021-12-24T23:17:36.357 回答