有没有办法在超出范围之前释放绑定? [英] Is there a way to release a binding before it goes out of scope?

查看:48
本文介绍了有没有办法在超出范围之前释放绑定?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用正则表达式解析文件:

I'm trying to parse a file using regexes:

extern crate regex; // 1.0.1

use regex::Regex;

fn example(
    section_header_pattern: Regex,
    section_name: &str,
    mut line: String,
    mut is_in_right_section: bool,
) {
    loop {
        if let Some(m) = section_header_pattern
            .captures(&line)
            .and_then(|c| c.get(1))
        {
            is_in_right_section = m.as_str().eq(section_name);
            line.clear();
            continue;
        }
    }
}

fn main() {}

...但是编译器抱怨,因为 RegExcaptures() 方法有一个在匹配的生命周期内持续的借用:

...but the compiler complains because the RegEx's captures() method has a borrow which endures for the lifetime of the match:

error[E0502]: cannot borrow `line` as mutable because it is also borrowed as immutable
  --> src/main.rs:17:13
   |
13 |             .captures(&line)
   |                        ---- immutable borrow occurs here
...
17 |             line.clear();
   |             ^^^^ mutable borrow occurs here
18 |             continue;
19 |         }
   |         - immutable borrow ends here

当我到达 line.clear(); 时,我已经完成了 Match 并想清除缓冲区并移到下一行在文件中,无需进一步处理.有没有好的/干净/优雅/惯用的解决方案,还是我需要硬着头皮引入后续的if"块?

By the time I get to line.clear();, I'm done with the Match and would like to clear the buffer and move onto the next line in the file without further processing. Is there a good/clean/elegant/idiomatic solution or do I need to just bite the bullet and introduce a subsequent 'if' block?

推荐答案

简短回答:否

我完成了Match

你可能知道,但编译器不知道.具体来说,生命周期当前绑定到它们定义的词法范围.您正在寻找的功能称为 非词法生命周期.目前还不稳定,但计划在 Rust 2018 版本中启用.

You may be, but the compiler doesn't know that. Specifically, lifetimes are currently bound to the lexical scope they are defined in. The feature you are looking for is called non-lexical lifetimes. It's not stable now, but it's planned to be enabled in the Rust 2018 edition.

举个例子:

fn main() {
    let mut s = String::from("hello");

    let matched = &s[..];
    println!("{}", matched);

    s.clear();

    println!("{}", s);
}

在我们打印matched 之后,程序员可以告诉我们已经完成了,但是编译器说借用会持续到结束的}.解决方法是引入一个范围:

A programmer can tell we are done with matched after we print it, but the compiler says that the borrow lasts until the closing }. The fix is to introduce a scope:

fn main() {
    let mut s = String::from("hello");

    {
        let matched = &s[..];
        println!("{}", matched);
    }
    s.clear();

    println!("{}", s);
}

您的情况更加阴险,因为清除字符串的决定与字符串本身的借用值交织在一起.像这样的东西将是我第一个到达的地方:

Your case is more insidious, as the decision to clear the string is interwoven with the value of the borrow of the string itself. Something like this would be my first place to reach:

fn main() {
    let mut s = String::from("hello");

    let do_clear;

    {
        let matched = &s[..];
        println!("{}", matched);
        do_clear = matched.contains("ll");
    }

    if do_clear {
        s.clear();
    }

    println!("{}", s);
}

但是,您的特定情况可能能够被转换以避免多个 if/if let 语句:

However, your specific case might be able to be transformed to avoid multiple if / if let statements:

let is_in_right_section = section_header_pattern.captures(&line)
    .and_then(|c| c.get(1))
    .map_or(false, |m| m.as_str() == section_name);

if is_in_right_section {
    line.clear();
    continue;
}

如果您引入新的类型和/或方法,这看起来不会太糟糕.作为奖励,Regex 有一个地方可以存放:

Which wouldn't look too bad if you introduce a new type and/or method. As a bonus, there's a place for the Regex to live:

struct Section(Regex);

impl Section {
    fn is(&self, s: &str, section: &str) -> bool {
        self.0
            .captures(s)
            .and_then(|c| c.get(1))
            .map_or(false, |m| m.as_str() == section)
    }
}

// ----

if section.is(&line, section_name) {
    line.clear();
    continue;
}

<小时>

当启用 NLL 时,原始代码按原样工作:


The original code works as-is when NLL is enabled:

#![feature(nll)]

extern crate regex; // 1.0.1

use regex::Regex;

fn main() {
    let section_header_pattern = Regex::new(".").unwrap();
    let section_name = "";
    let mut line = String::new();
    let mut is_in_right_section = false;

    loop {
        if let Some(m) = section_header_pattern
            .captures(&line)
            .and_then(|c| c.get(1))
        {
            is_in_right_section = m.as_str().eq(section_name);
            line.clear();
            continue;
        }

        return; // I don't really want to loop
    }
}

这篇关于有没有办法在超出范围之前释放绑定?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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