如何避免在Rust中使用filter_map给出错误“返回引用当前函数拥有的数据的值”?

问题描述

我正在尝试使用filter_map做一些运动。 下面的函数创建一个BufRead,然后选择与正则表达式匹配的行。我希望输出"aaa",但是编译器给我错误

returns a value referencing data owned by the current function" at line 7 `reg.captures(ss)`.

我知道我无法返回引用函数所拥有数据的值。但是我不知道如何避免这种情况。当line的类型为&str时,它可以工作。但是这里line的类型是std::string::String

您能给我一些提示还是指导我一些文件。我已经阅读了一些文档,但不了解如何避免该错误

use regex::Regex; // 1.4.1
use std::io::{self,BufRead as _};

fn main() {
    let reg = Regex::new(r"^(a+)").unwrap();
    io::Cursor::new(b"aaa\nbbb\nccc")
        .lines()
        .filter_map(|line| {
            let ss = &line.unwrap()[..];
            reg.captures(ss)
        })
        .map(|cap| cap[1].to_string())
        .for_each(|x| println!("{}",x));
}

解决方法

在映射闭包内,line的类型为Result<String,_>,这意味着它拥有String。但是,reg.captures()返回的值包含对该字符串中的切片的引用。函数无法返回对其拥有的值的引用,因为当函数返回时,这些值将被删除,从而使引用无效。

由于无论如何在filter_map之后立即创建一个新的拥有价值,因此您可以将该部分移入内部,以便仅在闭包内使用引用:

io::Cursor::new(b"aaa\nbbb\nccc")
    .lines()
    .filter_map(|line| {
        let ss = &line.unwrap()[..];
        reg.captures(ss).map(|cap| cap[1].to_string())
    })
    .for_each(|x| println!("{}",x));
,
use regex::Regex; // 1.4.1
use std::io::{self,BufRead as _};

fn main() {
    let reg = Regex::new(r"^(a+)").unwrap();
    io::Cursor::new(b"aaa\nbbb\nccc")
        .lines()
        .filter_map(|line| {
            let ss = &line.unwrap()[..];
            reg.captures(ss)
               // Cannot returns referencing `&str` owned by the current function(closure),// but a owned captured substring here
               .map(|cap| cap[1].to_string())
        })
        .for_each(|x| println!("{}",x));
}