I have function like this. I want to change function f's argument &'a [u8] to &'a Vec<u8> and its return type Vec<&'a [u8]> to Vec<&'a Vect<u8>>.
After changing the code, Rust cargo build complains the error returns a reference to data owned by the current function. I know like 1. 2 I have to store the variable somewhere outside my closure so that the life time can stay longer if I understand that error correctly. However, I do not know how to change that.
My attempting:
Add .as_ref before the windows(2), but there is no as_ref() function.
Create another myf fn fn myf<'a>(piece: &'a Vec<u8>, part: Vec<&'a (usize, u32)>) -> &'a Vec<u8> { &piece[part[0].0..part[1].0].to_vec() }, and replace .map(|part| &piece[part[0].0..part[1].0].to_vec()) with .map(|part| myf). An error value of type Vec<&Vec<u8>> cannot be built from std::iter::Iterator<Item=for<'a> fn(&'a Vec<u8>, Vec<&'a (usize, u32)>) -> &'a Vec<u8> {myf}> is thrown.
How to correct this error? Thanks
/* With this function the program can get compiled, and is executed successfully.
fn f<'a>(piece: &'a [u8]) -> Vec<&'a [u8]> {
[(0, 4294967295u32), (2, 4294967295u32), (4, 4294967295u32)]
.windows(2)
.map(|part| &piece[part[0].0..part[1].0])
.collect()
}
*/
// this one throws returns a reference to data owned by the current function error
fn f<'a>(piece: &'a Vec<u8>) -> Vec<&'a Vec<u8>> {
[(0, 4294967295u32), (2, 4294967295u32), (4, 4294967295u32)]
.windows(2)
.map(|part| &piece[part[0].0..part[1].0].to_vec())
.collect()
}
fn main() {
let vec = &Vec::from(b"abcd");
let result = f(vec);
println!("result: {:?}", result);
}
So it's because the data created in the closure is short live, which is destroyed after .map() function. After that the code continues to call collect(), which requires the use the data created inside the closure i.e. &piece[part[0].0..part[1].0]. Therefore, rather than calling collect() after map(), we let the code accomplishes its function first - returning an impl Iterator<Item= &'a[u8]>. Then, followed by the function f, calling the collect() because in the main function after f(vec), the temporary data created now is still alive, which then would be safe to execute the collect::<Vect<_>>(). Am I correct?
Also, how can I know what kind of function, other than to_vec(), collect(), that may create a temporary data structure owned by the function? It seems to me like it's a bit like some functions can be classified to action, while others are just expression in FP.
But the whole gist about not returning temporary values still holds. It's just that in this case the Vec doesn't hold a temporary value anymore.
It would be a case-by-case thing. You need to check the documentation for each method that you call, but to be honest methods that perform transformations usually have names that hint you what will happen, like (in)to_something, collect, from_something_else, etc.
Yes, of course. I just tried to do the minimum required changes to achieve what the OP wanted. Sometimes introducing more changes is counterproductive because the OP might not be able to pinpoint what the required change was.