Having trouble with function return

I am struggling with a function that is supposed to return either an f64 or an Error. I have tried many combinations, but no success. Thanks in advance. Also posted on Stackoverflow.

fn_rayon_parallel(&self) -> Result<f64, Box<dyn Error + Send + Sync>>  {

    let all_payoffs = (0..10000).into_par_iter().map( 
        |_| {   //things could go very wrong here        
                match self.get_one_payoff() {
                    Ok(payoff) => {Ok(payoff)},
                    Err(e) => Err(e)
                }
            }
    ).collect::<Result<Vec<_>, _>>();
    
    //this is the part I am struggling with, does not compile
    //I need to return either f64 or Error

    match all_payoffs {
        Ok(_v) => Ok(2.34 * (1.0/10000.0) * (all_payoffs.iter().sum::<f64>())),
        Err(e) => Err(From::from("There was an error in calculating Discounted Payoffs."))
    }

    
}

Error:

error[E0277]: the trait bound `f64: std::iter::Sum<&std::vec::Vec<f64>>` is not satisfied
  --> src/main.rs:81:69
   |
81 |             Ok(_v) => Ok(2.34 * (1.0/10000.0) * (all_payoffs.iter().sum::<f64>())),
   |                                                                     ^^^ the trait `std::iter::Sum<&std::vec::Vec<f64>>` is not implemented for `f64`
   |
   = help: the following implementations were found:
             <f64 as std::iter::Sum<&'a f64>>
             <f64 as std::iter::Sum>

https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=28d325ae926d36dcd50f526f7d2d2ffd

You should reference the thing you called _v instead of all_payoffs. You are currently calling Result::iter, which is not what you wanted, and this is why the item type in your iterator is Vec<f64>.

Note that we typically don't throw away the error information like that. It's standard to either return e directly or return something that includes the source error information.

1 Like

FWIW, Result also implements Sum, and you can use that in ParallelIterator::sum. So unless you really need that vector intermediate, you could do it like this:

    fn fn_rayon_parallel(&self) -> Result<f64, Box<dyn Error + Send + Sync>> {
        let sum_result = (0..10000)
            .into_par_iter()
            .map(|_| {
                //things could go very wrong here
                match self.get_one_payoff() {
                    Ok(payoff) => Ok(payoff),
                    Err(e) => Err(e),
                }
            })
            .sum::<Result<f64, _>>();

        match sum_result {
            Ok(x) => Ok(2.34 * (1.0 / 10000.0) * x),
            Err(e) => Err(From::from(
                "There was an error in calculating Discounted Payoffs.",
            )),
        }
    }

Awesome tip! Thanks

Thanks! Any idea how do I return the error directly back to the caller?

You can either return Err(e.into()) or use the question mark operator to replace the match with

Ok(2.34 * (1.0/10000.0) * (all_payoffs?.iter().sum::<f64>()))
1 Like

Got it. Thank you.

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.