无法使用 str.lines() 函数为每个循环绑定生存期

Unable to bound lifetime in for each loop using str.lines() function

提问人:Alex Licata 提问时间:11/2/2023 最后编辑:Alex Licata 更新时间:11/10/2023 访问量:63

问:

我是 rust 的新手,我正在构建 grep 命令的实现来学习这门语言。 我正在尝试创建一个函数以不区分大小写的方式匹配搜索查询,但是在处理迭代器在for循环中返回的值的生存期时遇到问题。str.lines()

这是一个最小的可重现示例,其中包含我正在实现的函数:

use grep::{run, Config};
use std::{env::args, process};

pub struct Config {
    file_path: String,
    query: String,
}
fn main() {
    let contents: Config =Config {query: "Hello world!".to_owned(), file_path: "test".to_owned()};
    let matches = search_case_sensitive(&config, &contents);
    print_matches(&matches);
    Ok(config)
}

type Match<'a> = Vec<(&'a str, &'a str, &'a str)>;

// this function causes the compile error
// contents -> the full text content of the file i previously read
// config.query -> the string i'm searching for inside contents
fn search_case_insensitive<'a>(config: &Config, contents: &'a str) -> Match<'a> {
    let mut matches: Match<'a> = Vec::new();
    let query = config.query.to_lowercase();
    for line in contents.lines() {
        let indexes = line.to_lowercase().match_indices(&query);
        for (i, found) in indexes {
            let prev = &line[..i];
            let next = &line[i + found.len()..];
            matches.push((prev, found, next));
        }
    }
    matches
}

我在编译时收到此错误:

error[E0716]: temporary value dropped while borrowed
  --> src/lib.rs:34:23
   |
34 |         let indexes = line.to_lowercase().match_indices(&query);
   |                       ^^^^^^^^^^^^^^^^^^^                      - temporary value is freed at the end of this statement
   |                       |
   |                       creates a temporary value which is freed while still in use
35 |         for (i, found) in indexes {
   |                           ------- borrow later used here
   |
   = note: consider using a `let` binding to create a longer lived value

据我所知,应该以生命周期为限,因为它是对每个元素的引用,但这并没有发生,所以不是借来的,而是移动的,我活得不够长,无法用于。line'acontentslineindexes

我怎样才能从内容中借用一行并将其绑定到生命周期?'a

字符串 迭 代 所有权 for-in-loop

评论

1赞 Chayim Friedman 11/2/2023
请发布最小可重复示例
0赞 Alex Licata 11/10/2023
@ChayimFriedman,我用一个最小的可重复的例子编辑了我的问题

答:

1赞 Chayim Friedman 11/2/2023 #1

问题是它是函数的本地函数,但您正在返回它。line.to_lowercase()

最简单的解决方法是制作一个 :String

type Match<'a> = Vec<(&'a str, String, &'a str)>;

// contents -> the full text content of the file i previously read
// config.query -> the string i'm searching for inside contents
fn search_case_insensitive<'a>(config: &Config, contents: &'a str) -> Match<'a> {
    let mut matches: Match<'a> = Vec::new();
    let query = config.query.to_lowercase();
    for line in contents.lines() {
        let line_lowercased = line.to_lowercase();
        let indexes = line_lowercased.match_indices(&query);
        for (i, found) in indexes {
            let prev = &line[..i];
            let next = &line[i + found.len()..];
            matches.push((prev, found.to_owned(), next));
        }
    }
    matches
}

但是,请注意,您的代码仍然不正确。具体来说,可以更改字符索引,甚至在一般情况下,降低两个字符串并比较它们对于Unicode进行不区分大小写的比较是不够的to_lowercase()

评论

0赞 Alex Licata 11/10/2023
谢谢你的回答,它解决了我的问题!