Rust 选项的生命周期::map';s论点

Rust 选项的生命周期::map';s论点,rust,Rust,我将一个字符串放入选项并尝试在其上映射,例如修剪字符串: 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); } 编译

我将一个字符串放入
选项
并尝试在其上映射,例如修剪字符串:

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);
}
编译器显示一个生存期错误

错误[E0597]:`z`活得不够长
-->src/main.rs:5:27
|
5 |设x=s|u opt.map(| z | z.trim());
|^-`z`在还借来的时候掉在这里了
|                           |
|借来的价值活得不够长
...
9 | }
|-借来的价值需要一直存在到这里
这一点很清楚,因为
z
仅在闭包中定义,并且参数是按值传递的

既然原始变量
s
适用于整个块,编译器难道不能找出
z
实际上是
s

我唯一能做到这一点的方法是将
添加到_string
(请参见注释行),然后创建一个新的string对象

我发现的另一个解决方案是使
s_opt
成为
选项的一种类型(请参见第二个代码块),但由于函数不能返回这种类型,因此这实际上不是一个选项

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);
}
fn我的地图选项&r str,
{
匹配*o{
无=>无,
一些(参考x)=>一些(f(x)),
}
}
fn main(){
let s=“我想要修剪”。to_string();
让s_opt=Some(s);
设x=my_map(&s_opt,| x | x.trim());
println!(“{:?}”,x);
}

map
函数使用迭代值,因此在调用给定闭包后,这些值不再存在。不能返回对它们的引用

最好的解决方案是直接在
字符串上进行就地修剪。遗憾的是,目前标准库中没有

您的第二个解决方案也可以通过一个小的改变。使用
&str
代替
&String

fn main() {
    let s = "text".to_string();
    let s_opt = Some(s.as_str());
    let x = s_opt.map(|z| z.trim());
    println!("{:?}", x);
}

如前所述,
Option::map
使用原始值生成输出值。这是最灵活、最高效的实现,因为您可以转换
选项。一旦您有了
选项
,您就可以使用它而不会失去原始
选项的所有权


谢谢PEPP的回复。实际上,我在使用std::io时遇到了问题。返回的类型是
IoResult
(例如read\u line)。因此,不能使用第二种解决方案。因此,我必须使用
作为_slice().trim().to _string()
解决方案或使用try!宏并将其包装在一个附加函数中。我说得对吗?
fn main() {
    let s = Some("     i want to be trimmed    ".to_string());

    let x = s.as_ref().map(|z| z.trim());

    println!("{:?}", x);
}