0

我发现不可能使用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]>>`

我不明白这两种类型是什么意思,但是有什么特殊的原因为什么没有实现呢?

4

2 回答 2

2

in的Subtraitndarray::ArrayBase没有为&mut参数实现(它用于对其他数组的不可变引用)。它不是必需的,因为不应修改右手值。第二个操作数是 a &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;

这假设a并且b是在其他地方获得的。事实上,您可以让这些变量拥有数组:

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;
于 2018-03-22T14:49:15.027 回答
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]>>`

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

ndarray::ScalarOperand`&mut ndarray::ArrayBase 未实现该特征

出现此错误的原因是 Rust 在匹配特征时不执行强制:如果某些类型存在 impl 并强制为UT则不U构成 for 的实现T(直接从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`
于 2018-03-23T14:06:35.823 回答