I have a HashMap where the key is derived from the value, so I want to not reproduce that derivation code every time.
Local functions don't work since they cannot access the local variable, and a closure fails as soon as anything else wants to use the map.
Here a simplified example:
use std::collections::HashMap;
fn main() {
let mut map: HashMap<usize, String> = HashMap::new();
let mut add_string = |string: String| {
map.insert(string.len(), string);
};
add_string("hi".to_string());
map.get(&1);
add_string("ho".to_string());
}
Which produces:
error[E0502]: cannot borrow `map` as immutable because it is also borrowed as mutable
--> src/bin/question.rs:11:9
|
5 | let mut add_string = |string: String| {
| ---------------- mutable borrow occurs here
6 | map.insert(string.len(), string);
| --- first borrow occurs due to use of `map` in closure
...
10 | add_string("ho".to_string());
| ---------- mutable borrow later used here
11 | map.get(&1);
| ^^^ immutable borrow occurs here
The alternative I found is to define and implement a trait:
use std::collections::HashMap;
fn main() {
let mut map: HashMap<usize, String> = HashMap::new();
map.add_string("hi".to_string());
map.get(&1);
map.add_string("ho".to_string());
}
trait InsertString {
fn add_string(&mut self, event: String);
}
impl InsertString for HashMap<usize, String> {
fn add_string(&mut self, event: String) {
self.insert(event.len(), event);
}
}
The syntax inside main()
is fine, but I find those 8 lines below adding too much noise.
For example, in Kotlin I could accomplish similar with an extension function without any noise:
fun HashMap<Int, String>.insert(string: String) =
this.insert(string.length, string)
Is there not a more idiomatic way than defining a specific trait for one-time use?
I started learning Rust a few days ago after years in OOP and a bit of functional programming experience,
so feel free to correct me if there is something totally different I should be doing.
I also found the possibility of passing a mutable reference, but again the code seems kinda noisy:
let mut add_string = |map: &mut HashMap<usize, String>, string: String| {
map.insert(string.len(), string);
};
add_string(&mut map, "hi".to_string());
add_string(&mut map, "h0".to_string());