有没有办法在绑定超出范围之前释放绑定?
Is there a way to release a binding before it goes out of scope?
我正在尝试使用正则表达式解析文件:
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() {}
...但是编译器会抱怨,因为 RegEx
的 captures()
方法有一个借用,它会在匹配的生命周期内持续存在:
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
并且想清除缓冲区并移至文件中的下一行而不进行进一步处理。是否有 good/clean/elegant/idiomatic 解决方案,还是我需要硬着头皮引入后续的 'if' 块?
简答:否
I'm done with the Match
你可能知道,但编译器不知道。具体来说,生命周期当前绑定到定义它们的词法范围。您正在寻找的功能称为 non-lexical lifetimes。目前还不稳定,但计划在Rust 2018版本中启用。
举个例子:
fn main() {
let mut s = String::from("hello");
let matched = &s[..];
println!("{}", matched);
s.clear();
println!("{}", s);
}
程序员可以在我们打印后告诉我们已经完成了 matched
,但是编译器说借用持续到结束 }
。解决方法是引入一个范围:
fn main() {
let mut s = String::from("hello");
{
let matched = &s[..];
println!("{}", matched);
}
s.clear();
println!("{}", s);
}
你的情况更隐蔽,因为清除字符串的决定与字符串本身的借用值交织在一起。像这样的东西将是我到达的第一个地方:
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
语句:
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;
}
如果引入一种新的类型 and/or 方法,这看起来不会太糟糕。作为奖励,Regex
有地方住:
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 时原始代码有效 as-is:
#![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
}
}
我正在尝试使用正则表达式解析文件:
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() {}
...但是编译器会抱怨,因为 RegEx
的 captures()
方法有一个借用,它会在匹配的生命周期内持续存在:
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
并且想清除缓冲区并移至文件中的下一行而不进行进一步处理。是否有 good/clean/elegant/idiomatic 解决方案,还是我需要硬着头皮引入后续的 'if' 块?
简答:否
I'm done with the
Match
你可能知道,但编译器不知道。具体来说,生命周期当前绑定到定义它们的词法范围。您正在寻找的功能称为 non-lexical lifetimes。目前还不稳定,但计划在Rust 2018版本中启用。
举个例子:
fn main() {
let mut s = String::from("hello");
let matched = &s[..];
println!("{}", matched);
s.clear();
println!("{}", s);
}
程序员可以在我们打印后告诉我们已经完成了 matched
,但是编译器说借用持续到结束 }
。解决方法是引入一个范围:
fn main() {
let mut s = String::from("hello");
{
let matched = &s[..];
println!("{}", matched);
}
s.clear();
println!("{}", s);
}
你的情况更隐蔽,因为清除字符串的决定与字符串本身的借用值交织在一起。像这样的东西将是我到达的第一个地方:
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
语句:
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;
}
如果引入一种新的类型 and/or 方法,这看起来不会太糟糕。作为奖励,Regex
有地方住:
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 时原始代码有效 as-is:
#![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
}
}