如何在&amp; ndarray :: Array1 <f64>和&amp; mut Array1 <f64>之间进行减法?

时间:2018-03-22 14:23:34

标签: multidimensional-array rust rust-crates

我发现使用ndarray crate在不可变数组引用和可变数组引用之间进行减法是不可能的:

#[macro_use]
extern crate ndarray;

use ndarray::Array1;

fn main() {
    let a: &Array1<f64> = &array![3.0, 2.0, 1.0];
    let b: &mut Array1<f64> = &mut array![1.0, 1.0, 1.0];
    let c = a - &b.view();          //   This compiles
    let d = a - b;                  //   This fails to compile
}

我得到的错误信息是:

let d = a - b;
          ^ no implementation for `f64 - &mut ndarray::ArrayBase<ndarray::OwnedRepr<f64>, ndarray::Dim<[usize; 1]>>`

我不明白这两种类型的含义,但是有什么特殊原因可以解决这个问题吗?

2 个答案:

答案 0 :(得分:2)

&mut参数未实现Sub trait in ndarray::ArrayBase(它用于对其他数组的不可变引用)。不需要它,因为不应修改右手值。第二个操作数是&mut Array<A, D>,它最终成为弱化为不可变引用的类型不会自动发生的情况之一。不过,您可以明确地重新借用这个值:

let a: &Array1<f64> = &array![3.0, 2.0, 1.0]; 
let b: &mut Array1<f64> = &mut array![1.0, 1.0, 1.0]; 
let c = a - &b.view();
let d = a - &*b;

这假设ab是在其他地方获得的。实际上,您可以改为使这些变量拥有数组:

let a: Array1<f64> = array![3.0, 2.0, 1.0]; 
let mut b: Array1<f64> = array![1.0, 1.0, 1.0]; 
let c = &a - &b.view();
let d = &a - &b;

答案 1 :(得分:1)

完整的错误消息是:

error[E0277]: the trait bound `f64: std::ops::Sub<&mut ndarray::ArrayBase<ndarray::OwnedRepr<f64>, ndarray::Dim<[usize; 1]>>>` is not satisfied
  --> src/main.rs:10:15
   |
10 |     let d = a - b;
   |               ^ no implementation for `f64 - &mut ndarray::ArrayBase<ndarray::OwnedRepr<f64>, ndarray::Dim<[usize; 1]>>`
   |
   = help: the trait `std::ops::Sub<&mut ndarray::ArrayBase<ndarray::OwnedRepr<f64>, ndarray::Dim<[usize; 1]>>>` is not implemented for `f64`
   = note: required because of the requirements on the impl of `std::ops::Sub<&mut ndarray::ArrayBase<ndarray::OwnedRepr<f64>, ndarray::Dim<[usize; 1]>>>` for `&ndarray::ArrayBase<ndarray::OwnedRepr<f64>, ndarray::Dim<[usize; 1]>>`

error[E0277]: the trait bound `&mut ndarray::ArrayBase<ndarray::OwnedRepr<f64>, ndarray::Dim<[usize; 1]>>: ndarray::ScalarOperand` is not satisfied
  --> src/main.rs:10:15
   |
10 |     let d = a - b;
   |               ^ the trait `ndarray::ScalarOperand` is not implemented for `&mut ndarray::ArrayBase<ndarray::OwnedRepr<f64>, ndarray::Dim<[usize; 1]>>`
   |
   = note: required because of the requirements on the impl of `std::ops::Sub<&mut ndarray::ArrayBase<ndarray::OwnedRepr<f64>, ndarray::Dim<[usize; 1]>>>` for `&ndarray::ArrayBase<ndarray::OwnedRepr<f64>, ndarray::Dim<[usize; 1]>>`

第一条错误信息对我来说非常模糊,但第二条更具启发性:

  

没有为`&amp; mut ndarray :: ArrayBase

实现特征ndarray::ScalarOperand

出现此错误的原因是Rust在匹配特征时不执行强制:如果某个类型UT强制要求U,则不构成T的实施(直接从the Nomicon复制)

没有进入ndarray内部,这是一个重现同样问题的最小例子:

trait MyShape {}

fn foo<T: MyShape>(x: T) -> T {
    x
}

impl<'a> MyShape for &'a i32 {}

fn main() {
    let mut num = 1;
    let arg: &mut i32 = &mut num;
    foo(arg);
}

结果:

error[E0277]: the trait bound `&mut i32: MyShape` is not satisfied
  --> src/main.rs:12:5
   |
12 |     foo(arg);
   |     ^^^ the trait `MyShape` is not implemented for `&mut i32`
   |
   = help: the following implementations were found:
             <&'a i32 as MyShape>
   = note: required by `foo`