Working with arrays/vecs in functions

I'm trying a simple code, in which I've 2 elements of vec type (or or 1s array type) bith elements are of the same size, and I just want to add the items with the same index together.
I wanted to try doing it using functional programming like x.iter().map(|v| ...) but did not know how to do it, so tried doing it the classical way, and wrote the below function, but got stuck with borrowing and referencing and got errors:

Tried the below code:

fn foo(x: &[i32], y: &[i32]) -> &'static [i32] {
    let r: &'static [i32];
    for i in x {
            r[i] = x[i] * y[i];
    }
//  functional approach failed:   r = x.iter().map(|v| *v) * y.iter().map(|v| *v).collect();
    r
}

Got the below errors:

error[E0277]: the type `[i32]` cannot be indexed by `&i32`
  --> src\main.rs:42:13
   |
42 |             r[i] = x[i] * y[i];
   |             ^^^^ slice indices are of type `usize` or ranges of `usize`
   |
   = help: the trait `std::slice::SliceIndex<[i32]>` is not implemented for `&i32`
   = note: required because of the requirements on the impl of `std::ops::Index<&i32>` for `[i32]`

error[E0277]: the type `[i32]` cannot be indexed by `&i32`
  --> src\main.rs:42:20
   |
42 |             r[i] = x[i] * y[i];
   |                    ^^^^ slice indices are of type `usize` or ranges of `usize`
   |
   = help: the trait `std::slice::SliceIndex<[i32]>` is not implemented for `&i32`
   = note: required because of the requirements on the impl of `std::ops::Index<&i32>` for `[i32]`

error[E0277]: the type `[i32]` cannot be indexed by `&i32`
  --> src\main.rs:42:27
   |
42 |             r[i] = x[i] * y[i];
   |                           ^^^^ slice indices are of type `usize` or ranges of `usize`
   |
   = help: the trait `std::slice::SliceIndex<[i32]>` is not implemented for `&i32`
   = note: required because of the requirements on the impl of `std::ops::Index<&i32>` for `[i32]`

error: aborting due to 3 previous errors

You will need to return a Vec

fn foo(x: &[i32], y: &[i32]) -> Vec<i32> {
    x.iter().zip(y).map(|(x, y)| x * y).collect()
}

This will return a vec that has the same length as the shorter of the two slices.

1 Like

Thanks, this solved my issue, but what if I want to work with arrays, for doing something more complicated, like working with multidimensional arrays, and return multidimensional array?

How are you representing the multi-dimensional arrays? Like Vec<Vec<_>> or [[_; M]; N] or something else?

Like this.

mmm, actually what I'm trying so far is a mix, it is this:

    let apple_pi = vec![1, 0, 0];
    let burger = vec![0, 1, 0];
    let chekin = vec![0, 0, 1];
    let food: [&Vec<i32>; 3] = [&apple_pi, &burger, &chekin];

    let sunny = vec![1, 0];
    let rainy = vec![0, 1];
    let weather: [&Vec<i32>; 2] = [&sunny, &rainy];

And I want to do array multiplication myself, without using ready crate.

// 3 x 2 * 2 x 1 = 3 x 1
 [&Vec<i32>; 3] * [&Vec<i32>; 2] = [&Vec<i32>; 1] // or &Vec<i32> of 3 elememts

Array multiplication is a bit complicated because you have to iterate over strides or transpose the second matrix which will need to allocate. There isn't a way to easily do it from std.

I C, thanks for your efforts, appreciated.

I made this one, not sure if can be simplified, but it is working with me needs so far:

type OryxResult<T> = std::result::Result<T, Box<dyn std::error::Error>>;
fn foo(x: &[&Vec<f64>], y: &[&Vec<f64>]) -> OryxResult<Vec<f64>> {
    // n x m * m x p = n x p
    let m = x.len();   // 2 // number of vecs
    let n = x[0].len();  // 3 // vec length

    let _m = y[0].len();   // 2  // vec length
    let p = y.len();  // 1 // number of vecs
    if x.len() != y[0].len() {
        Err(format!("cross dimentional is invalid"))?
    } else {
        //let mut array: Vec<Vec<i32>> = vec![vec![Default::default(); p]; n];
        let mut array: Vec<f64> = vec![Default::default(); n];

        for i in 0..n {  // 3;
            for j in 0..m {   // 2
                for k in 0..p {   // 1
                //    array[i][k] += x[j][i] * y[k][j];
                    array[i] += x[j][i] * y[k][j];
                }
            }
        }
        Ok(array)
    }
}

And calling it as:

    match foo(&food, &weather) {
        Err(e) => println!("Error = {:?}", e),
        Ok(r) => {
            println!("result = {:?}", r);
        }
    } ;