首页 > 解决方案 > 如何修改在循环中使用自身的 Cow 变量?

问题描述

我正在尝试删除字符串中的所有括号。没有想得太难,我只是做了一个简单的正则表达式替换(即,有问题的问题并不是特别是关于摆脱任意级别的嵌套括号,但如果你愿意,请随时在评论中提出更好的方法来做到这一点)。

use regex::Regex;

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let input = "Text (with some (nested) parentheses)!";
    let re = Regex::new(r"\([^()]*\)")?;

    let output = re.replace_all(&input, "");
    let output = re.replace_all(&output, "");
    //    let output = re.replace_all(&output, "");
    //    let output = re.replace_all(&output, "");
    //    let output = re.replace_all(&output, "");
    //    let output = re.replace_all(&output, "");
    // ...

    assert_eq!("Text !", output);

    println!("Works!");

    Ok(())
}

因为我不知道括号的嵌套程度,所以我需要在循环中进行替换,而不是重复“足够多次”。然而,创建一个循环会创建一个新的范围,这就是我在与借用检查器的讨论中遇到的死点。

显示我在循环中尝试做的最简单的情况是:

    let mut output = re.replace_all(&input, "");
    while re.is_match(&output) {
        output = re.replace_all(&output, "");
    }

但是,因为我正在分配一个借来的变量,所以无法做到这一点:

error[E0506]: cannot assign to `output` because it is borrowed
 --> src/main.rs:9:9
  |
9 |         output = re.replace_all(&output, "");
  |         ^^^^^^                  ------- borrow of `output` occurs here
  |         |
  |         assignment to borrowed `output` occurs here
  |         borrow later used here

理想情况下,我想做的是创建具有相同名称的新变量绑定,但使用let output =会影响外部变量绑定,因此循环将无限循环。

无论我创建什么内部或外部临时变量,我都无法让它做我想做的事。re.replace_all()我还尝试使用return的事实,Cow并尝试在几个地方使用.to_owned()and .to_string(),但这也无济于事。

这是一个游乐场的链接

标签: loopsrustborrow-checkerborrowing

解决方案


re.replace_all()返回Cow

这是问题的根源。编译器知道返回值可能会引用output,但它也会替换 output,导致output立即被删除。如果允许,引用将指向未分配的内存,从而导致内存不安全。

解决方案是完全避免借贷。

尝试使用.to_owned()

to_ownedon aCow只是返回相同的Cow. 也许你的意思是into_owned

let mut output = re.replace_all(&input, "").into_owned();
while re.is_match(&output) {
    output = re.replace_all(&output, "").into_owned();
}

.to_string()在几个地方

这也有效:

let mut output = re.replace_all(&input, "").to_string();
while re.is_match(&output) {
    output = re.replace_all(&output, "").to_string();
}

推荐阅读