I placee a string into an Option
and try to map over it, e.g. to trim the string:
fn main() {
let s = " i want to be trimmed ".to_string();
let s_opt = Some(s);
let x = s_opt.map(|z| z.trim());
// let x = s_opt.map(|z| z.trim().to_string());
println!("'{:?}'", x);
}
The compiler shows a lifetime error
error[E0597]: `z` does not live long enough
--> src/main.rs:5:27
|
5 | let x = s_opt.map(|z| z.trim());
| ^ - `z` dropped here while still borrowed
| |
| borrowed value does not live long enough
...
9 | }
| - borrowed value needs to live until here
This is clear, since z
is only defined in the closure and the argument is passed by value.
Since the original variable s
lives for the entire block, shouldn't the compiler be able to figure out that z
is actually s
?
The only way I can get this to work is by adding to_string
(see the commented line), but then I am creating a new string object.
Another solution I found is to make s_opt
a type of Option<&String>
(see the second code block), but since functions can't return this kind of type this is not really an option.
fn main() {
let s = " i want to be trimmed ".to_string();
let s_opt = Some(&s);
let x = s_opt.map(|z| z.trim());
println!("'{:?}'", x);
}
Is there something I've overlooked or wouldn't it be better if the default implementation of map
would be similar to this?
fn my_map<'r, F>(o: &'r Option<String>, f: F) -> Option<&'r str>
where
F: Fn(&'r String) -> &'r str,
{
match *o {
None => None,
Some(ref x) => Some(f(x)),
}
}
fn main() {
let s = " i want to be trimmed ".to_string();
let s_opt = Some(s);
let x = my_map(&s_opt, |x| x.trim());
println!("'{:?}'", x);
}