I am trying to copy a string outside of a closure by cloning it, but the compiler is telling me that k escapes the closure body.
I thought the clone would allow me to get around to this, but that does not work.
Any idea how I could achieve a behavior similar to the one describe hereafter? I am in reality trying to read off a file and yield each line in a closure, to maybe copy some of them.
fn copier(src: &Vec<&str>, mut closure: impl FnMut(&str) -> ()) {
for s in src {
closure(s);
}
}
fn main() {
let source: Vec::<&str> = vec!["aa", "bb"];
let mut new_vec: Vec::<&str> = vec![];
copier(&source, |k| new_vec.push(k.clone()));
println!("{:?}", new_vec);
}
Error:
Standard Error
Compiling playground v0.0.1 (/playground)
error[E0521]: borrowed data escapes outside of closure
--> src/main.rs:10:25
|
9 | let mut new_vec: Vec::<&str> = vec![];
| ---------- `new_vec` declared here, outside of the closure body
10 | copier(&source, |k| new_vec.push(k.clone()));
| - ^^^^^^^^^^^^^^^^^^^^^^ `k` escapes the closure body here
| |
| `k` is a reference that is only valid in the closure body
Oh! Thanks @Masklinn! I was copying the reference, not the content.
This helps my understanding of memory management, I come from JS so there's a long way...
Additionally, I needed to change the type of what new_vec contains to be String. If I understand well, I can't push an &str into it, because the String it refers to (created with the call to to_owned) gets dropped at the end of the closure.
So the newly created Strings needs to move out of it.
Updated solution:
fn copier(src: &Vec<&str>, mut closure: impl FnMut(&str) -> ()) {
for s in src {
closure(s);
}
}
fn main() {
let source: Vec::<&str> = vec!["aa", "bb"];
let mut new_vec: Vec::<String> = vec![];
copier(&source, |k| new_vec.push(k.to_owned()));
println!("{:?}", new_vec);
}