Pull me out of insanity. Can't wrap my head around this error: expected `std::vec::Vec<f64>`, found `[_; 4]` (expected &-ptr, found array of 4 elements) [E0308]


#1

Here’s the code, I am trying to run:

use std::vec::Vec;

fn main () {
    let percentages = [10, 11, 23, 34];

    let balance = compound( 1000.00, percentages);

    println!("Your balance is {}", balance );
}

fn compound(investment: f64, returns: Vec<f64> ) -> f64 {
    returns.fold(investment, | value, perc | value * ( 1 + (&perc / 100 )) )
}

A detailed explanation on why I am getting the found : [_; 4] would be much appreciated.

Thanks in advance for your time.


#2

You seem to have defined percentages as an array.

[10, 11, 23, 34]

is the syntax for arrays, in this case an array of length 4. Hence the type error.

There is a convenient macro you can use to make a Vec from an array, which looks like this:

vec![a, b, c, ...]

In your case, you’ve actually written integers instead of floating point numbers, so you’d want to initialize percentages like so:

let percentages = vec![10.0, 11.0, 23.0, 34.0];

#3

Thanks for the tips @zsck, I tried them:

use std::vec::Vec;

fn main () {
    let percentages = vec![10.0, 11.0, 23.0, 34.0];

    let balance = compound( 1000.00, percentages);

    println!("Your balance is {}", balance );
}

fn compound(investment: f64, returns: Vec<f64> ) -> f64 {
    returns.fold(investment, | value, perc | value * ( 1 + (perc / 100 )) )
}

Now, I am getting the error:

`error: no method named `fold` found for type `std::vec::Vec<f64>` in the current scope`

I am hacking up a trait tonight that implements this type of operation easily (passing integer or float and array[] -> f64) and share it on cargo, hopefully others won’t struggle with edge cases.

Guess I have been spoiled with how JS arrays work :slight_smile:


#4

Use Vec::iter() to get an iterator on which you can use the iterator methods. Also, you need to use floating point values instead of ints.

use std::vec::Vec;

fn main () {
    let percentages = vec![10.0, 11.0, 23.0, 34.0];

    let balance = compound( 1000.00, percentages);

    println!("Your balance is {}", balance );
}

fn compound(investment: f64, returns: Vec<f64> ) -> f64 {
    returns.iter().fold(investment, | value, perc | value * ( 1. + (perc / 100. )) )
}

Playground


#5

Now that the question of how to pass in Vecs has been answered, another point should be brought up:
If your argument type is a Vec, the ownership of the Vec is passed to the called function and so the Vec is no longer available to the caller. So, if you’d try something like:

let balance = compound( 1000.00, percentages);
let balance = compound( balance, percentages);

it will fail to compile with the error "use of moved value: percentages".

For this reason, a function like compound would usually take the returns Array/Vec as a reference. (i.e. &Vec, with the caller passing it using &percentages).
Now, once you take an immutable reference to a Vec, you can almost always rather take a slice (i.e. &[f64]), so that the caller can pass in data from a Vec OR an array:

fn main () {
    let percentages = [10., 11., 23., 34.];

    let balance = compound( 1000.00, &percentages);

    println!("Your balance is {}", balance );
}

fn compound(investment: f64, returns: &[f64] ) -> f64 {
    returns.iter().fold(investment, | value, &perc | value * ( 1. + (perc / 100. )) )
}

Playground


#6

Thanks for the insight @exoticorn.