如何修改在循环中使用自身的Cow变量? [英] How to modify a Cow variable that uses itself in a loop?

查看:59
本文介绍了如何修改在循环中使用自身的Cow变量?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试删除字符串中的所有括号.不必太费劲,我只是做一个简单的regexp替换(即,问题不是特别要摆脱嵌套括号的任意级别,而是可以随意在注释中提出一个更好的方法来解决此问题)).

使用regex::Regex;fn main()->结果<(),Box< dyn std :: error :: Error>>{让input =文本(带有(嵌套的)括号)!";让re = Regex :: new(r"\([^()] * \)")?;让输出= re.replace_all(& input,");让输出= re.replace_all(& output,");//让output = re.replace_all(& output,");//让output = re.replace_all(& output,");//让output = re.replace_all(& output,");//让output = re.replace_all(& output,");//...assert_eq!("Text!",输出);println!("Works!");好的(())} 

因为我不知道括号的嵌套方式,所以我需要循环进行替换,而不是重复足够多次".但是,创建循环会创建一个新的作用域,而这正是我在借阅检查器的讨论中遇到的一个僵局.

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

 让mut输出= re.replace_all(& input,");而re.is_match(& output){输出= re.replace_all(& output,");} 

但是由于我要分配给借来的变量而无法完成操作

 错误[E0506]:由于借用而无法分配给`output`->src/main.rs:9:9|9 |输出= re.replace_all(& output,");|^^^^^^ -------在这里借出`output`|||分配给借用的输出"|借来以后用在这里 

理想情况下,我想做的是创建具有相同名称的新变量绑定,但是使用 let output = 将遮盖外部变量绑定,因此循环将无限循环./p>

无论我创建什么内部或外部临时变量,我都无法使其执行我想要的操作.我还尝试使用 re.replace_all()返回 Cow 的事实,并尝试使用 .to_owned() .to_string()在几个地方,但这也无济于事.

这是一个链接到游乐场.

解决方案

re.replace_all()返回 Cow

这是问题的根源.编译器知道返回值可能引用了 output ,但也会返回 replace output ,从而导致 output 为立即掉线.如果允许,则引用将指向未分配的内存,从而导致内存不安全.

解决方案是完全避免借款.

使用 .to_owned()

尝试

Cow 上的

to_owned 仅返回相同的 Cow .也许您是说 into_owned ?

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

.to_string()在几个地方

这同样有效:

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

很遗憾您没有展示出解决问题的实际尝试,我们本可以帮助您了解为什么它们不起作用.

I am trying to remove all the parentheses in a string. Not thinking about it too hard, I just do a simple regexp replace (i.e. the problem in question is not particularly about getting rid of arbitrary levels of nested parentheses, but feel free to suggest a better way of doing that in a comment if you want).

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

Because I do not know how nested the parentheses will be, I need to do the replacement in a loop rather than repeating it "just enough times". Creating a loop, however, creates a new scope and that's where I'm hitting a dead point in the discussion with the borrow checker.

The simplest case that shows what I am trying to do in the loop would be:

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

However that cannot be done because I am assigning to a borrowed variable:

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

What I would like to do, ideally, is to create new variable binding with the same name, but using let output = will shadow the outer variable binding, so the loop would cycle infinitely.

No matter what inner or outer temporary variable I create I cannot make it do what I want. I also tried using the fact that re.replace_all() returns Cow and tried using .to_owned() and .to_string() in a couple of places, but that didn't help either.

Here's a link to a playground.

解决方案

re.replace_all() returns Cow

This is the root of the problem. The compiler knows that the return value might reference output, but is also will replace output, causing output to be dropped right away. If it allowed this, the reference would point to unallocated memory, leading to memory unsafety.

The solution is to avoid borrowing at all.

tried using .to_owned()

to_owned on a Cow just returns the same Cow. Perhaps you meant into_owned?

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

and .to_string() in a couple of places

This works as well:

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

It's a shame that you didn't show your actual attempts at solving the problem, we could have helped you understand why they didn't work.

这篇关于如何修改在循环中使用自身的Cow变量?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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