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

问题描述 投票:0回答:1

我是 Rust 新手,我正在构建 grep 命令的实现来学习这种语言。 我正在尝试创建一个函数来以不区分大小写的方式匹配搜索查询,但我在处理 for 循环中

str.lines()
迭代器返回的值的生命周期时遇到问题。

这是我正在实现的功能:

type Match<'a> = Vec<(&'a str, &'a str, &'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 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
应该限于
'a
的生命周期,因为它是对
contents
的每个元素的引用,但这并没有发生,所以
line
不是借用的,而是移动的,而我没有活得足够长,可以在
indexes
中使用。

如何从内容中借用行并将其绑定到

'a
生命周期?

string rust iterator ownership for-in-loop
1个回答
0
投票

问题是

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
}

但是请注意,您的代码仍然不正确。具体来说,

to_lowercase()
可以更改字符索引,甚至一般来说,小写两个字符串并比较它们也不足以进行与 Unicode 不区分大小写的比较。

© www.soinside.com 2019 - 2024. All rights reserved.