Option::map 参数的生命周期 [英] Lifetime of Option::map's argument

查看:58
本文介绍了Option::map 参数的生命周期的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我将一个字符串放入一个 Option 并尝试映射它,例如修剪字符串:

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

这很清楚,因为 z 仅在闭包中定义并且参数是按值传递的.

This is clear, since z is only defined in the closure and the argument is passed by value.

由于原始变量 s 存在于整个块中,编译器是否应该能够确定 z 实际上是 s?

Since the original variable s lives for the entire block, shouldn't the compiler be able to figure out that z is actually s?

我可以让它工作的唯一方法是添加 to_string(请参阅注释行),但随后我正在创建一个新的字符串对象.

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.

我发现的另一个解决方案是使 s_opt 成为一种 Option<&String>(请参阅第二个代码块),但由于函数无法返回此这种类型这不是一个真正的选择.

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);
}

是否有什么我忽略的地方,或者如果 map 的默认实现与此类似,会不会更好?

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);
}

推荐答案

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

The map function consumes iterated values so they do not exist after the call to the given closure anymore. You cannot return references to them.

最好的解决方案是直接对 String 进行就地修剪.遗憾的是,目前标准库中没有.

The best solution would be in-place trim on String directly. Sadly there is none in the standard library currently.

您的第二个解决方案也可以稍作改动.而不是 &String 你取一个 &str:

Your second solution is also possible with a small change. Instead of &String you take a &str:

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 参数的生命周期的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆