我将一个字符串放入Option
中,并尝试Map它,例如。要修剪字符串,请执行以下操作:
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);
}
编译器显示生存期错误
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
这很明显,因为z
只在闭包中定义,并且参数是通过值传递的。
由于原始变量s
存在于整个块中,编译器难道不应该能够识别出z
实际上是s
吗?
唯一的方法是添加to_string
(请参阅注解行),然后创建一个新的字符串对象。
我发现的另一个解决方案是将s_opt
设置为Option<&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());
println!("'{:?}'", x);
}
是否有什么我忽略了的地方,或者如果map
的默认实现与此类似不是更好吗?
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);
}
2条答案
按热度按时间rkttyhzu1#
map
函数使用迭代值,因此在调用给定闭包之后,这些值将不再存在。不能返回对它们的引用。最好的解决方案是直接在
String
上进行就地修剪。可惜的是,目前标准库中还没有。你的第二个解决方案也可以通过一个小的变化。而不是
&String
,你需要一个&str
:mnemlml82#
如上所述,
Option::map
* 消耗 * 原始值以产生输出值。这是最灵活和最有效的实现,因为您可以将Option<A>
转换为Option<B>
,而无需克隆原始值。这种情况下的解决方案是使用
Option::as_ref
将Option<String>
(实际上是&Option<String>
)转换为Option<&String>
。拥有Option<&String>
后,您可以使用它而不会失去原始Option<String>
的所有权: