A large array of structs to be processed and two different mutable arrays should hold the values.
I used par_iter and got the following error:
fn par_calculate_depreciation_for_assets(assets_to_depreciate: &Vec<Depreciation>) -> Result<(), Ferror> {
let mut acc_dep = 0;
let mut errors: Vec<String> = vec![];
let mut assets_record : Vec<AssetRecord> = Vec::new();
assets_to_depreciate.par_iter().for_each( |item| {
let result = calculate_monthly_depreciation(item);
if result.is_err()
{
errors.push(item.asset_code.clone());
}
else
{
let (asset, depreciated_asset) = result.unwrap();
build_csv_struct(item, &mut assets_record, asset);
}
});
append_to_csv(assets_record);
dbg!("Errors {:?} unprocessed", errors);
Ok(())
}
error[E0596]: cannot borrow `errors` as mutable, as it is a captured variable in a `Fn` closure
--> src/services/csv_services/dep_for_all_assets_in_csv_copy.rs:69:17
|
69 | errors.push(item.asset_code.clone());
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot borrow as mutable
The error you currently see is that errors
is mutably captured by your closure implementing the Fn
trait you pass to the for_each
call on your parallel iterator, which Rust does not allow.
There is a more fundamental problem with your current implementation, though. There is a race condition. What happens if two threads simultaneously try to add an element to errors
? You must make sure that access to errors
is mutually exclusive. I can really recommend reading the shared-state concurrency section of the Rust book: https://doc.rust-lang.org/book/ch16-03-shared-state.html.
Here a minimal example that fixes your error and the race condition, by wrapping errors
in a Mutex
:
use rayon::prelude::*;
use std::sync::Mutex;
fn par_calculate_depreciation_for_assets(assets_to_depreciate: &Vec<u8>) -> Vec<String> {
let errors: Mutex<Vec<String>> = Mutex::new(vec![]);
assets_to_depreciate.par_iter().for_each(|item| {
let mut errors = errors.lock().unwrap();
errors.push(item.to_string());
});
errors.into_inner().unwrap()
}
fn main() {
let errors = par_calculate_depreciation_for_assets(&vec![0, 1, 2, 3]);
assert_eq!(
errors,
vec![
"0".to_owned(),
"1".to_owned(),
"2".to_owned(),
"3".to_owned()
]
)
}