0

I am learning myself rust-ndarray and wrote this simple code.

use ndarray::prelude::*; 

fn main() {
    let mut a = Array2::<f64>::ones((3, 3));
    let b = (a*(a-0.5))*(a+2.0);
    println!("{:?}",b);

}

I expected the output to be

  [[ 1.5,  1.5,  1.5],
   [ 1.5,  1.5,  1.5],
   [ 1.5,  1.5,  1.5]]

But its giving this error

    |     let b = (a*(a-0.5))*(a+2.0);
    |                -------   ^ value used here after move
    |                |
    |                `a` moved due to usage in operator
Eka
  • 14,170
  • 38
  • 128
  • 212

1 Answers1

1

The operators take their arguments by value. This allows optimizations, for example reusing the same memory for the output if you no longer need the input after the operation. In ndarray addition is also implemented for references, so you can simply borrow the operands to tell the compiler that you want to keep using them later. However multiplication is only implemented for owned values (I'm not sure why), so you will need to either clone a or do the operations in two lines so you can move a in the second line:

let b = a.clone() * (&a-0.5) * (&a+2.0);

Playground

or

let b = (&a-0.5) * (&a+2.0);
let b = a * b;
// Can't use a from now on

Playground

Jmb
  • 18,893
  • 2
  • 28
  • 55
  • doesn't `mut` keyword used for these kind of problems and would help reusing the same variable multiple times? – Eka Oct 20 '20 at 09:57
  • 1
    @Eka It is not possible to (safely) take ownership from a `mut` reference. – L. F. Oct 20 '20 at 10:16
  • It's not a question of mutable vs not mutable, it's a question of moving vs borrowing. If you move a value then you can't reuse it, whereas you can borrow a value more than once (provided none of the borrows are `mut`). – Jmb Oct 20 '20 at 11:47