I’ve been trying to initiate a value (here hashbrown’s hashmap) with the following function:
use std::collections::HashMap;
use std::sync::{Arc, Mutex};
use std::thread;
#[derive(Clone)]
struct Entity;
fn create_value(center: (f32, f32), length: f32) -> HashMap<(i32, i32), Option<Entity>> {
let cities: Arc<Mutex<HashMap<(i32, i32), Option<Entity>>>> = Arc::default();
let mut handles = vec![];
for i in 0..5 {
for j in 0..5 {
let city_thread = Arc::clone(&cities);
handles.push(thread::spawn(move || {
// do stuff in parallel
if let Ok(mut cities) = city_thread.lock() {
cities.insert((i, j), None);
}
}));
}
}
for handle in handles {
handle.join().unwrap();
}
// this part is the problem
if let Ok(city) = cities.lock() {
let city = city.clone();
return city;
} else {
panic!()
}
}
I get the following error:
`cities` does not live long enough
the temporary is part of an expression at the end of a block;
consider forcing this temporary to be dropped sooner, before the block's local variables are dropped
I know I’m doing something wrong but I can’t find anything or a way to return the value.
>Solution :
We need to put the result of city.clone() in a variable that’s declared before the final if let block and move the return out of the if let block as well.
use std::collections::HashMap;
use std::sync::{Arc, Mutex};
use std::thread;
#[derive(Clone)]
struct Entity;
fn create_value(center: (f32, f32), length: f32) -> HashMap<(i32, i32), Option<Entity>> {
let cities: Arc<Mutex<HashMap<(i32, i32), Option<Entity>>>> = Arc::default();
let mut handles = vec![];
for i in 0..5 {
for j in 0..5 {
let city_thread = Arc::clone(&cities);
handles.push(thread::spawn(move || {
// do stuff in parallel
if let Ok(mut cities) = city_thread.lock() {
cities.insert((i, j), None);
}
}));
}
}
for handle in handles {
handle.join().unwrap();
}
let result;
if let Ok(city) = cities.lock() {
result = city.clone();
} else {
panic!()
}
result
}
Or, we can avoid having the if let be "an expression at the end of a block" by adding a semicolon after it. It’s weird, but it works!
use std::collections::HashMap;
use std::sync::{Arc, Mutex};
use std::thread;
#[derive(Clone)]
struct Entity;
fn create_value(center: (f32, f32), length: f32) -> HashMap<(i32, i32), Option<Entity>> {
let cities: Arc<Mutex<HashMap<(i32, i32), Option<Entity>>>> = Arc::default();
let mut handles = vec![];
for i in 0..5 {
for j in 0..5 {
let city_thread = Arc::clone(&cities);
handles.push(thread::spawn(move || {
// do stuff in parallel
if let Ok(mut cities) = city_thread.lock() {
cities.insert((i, j), None);
}
}));
}
}
for handle in handles {
handle.join().unwrap();
}
// this part is the problem
if let Ok(city) = cities.lock() {
let city = city.clone();
return city;
} else {
panic!()
}
;
}
(I’d recommend the first approach though.)