我正在尝试使用正则表达式解析文件:
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
并且想要清除缓冲区并移动到文件中的下一行而无需进一步处理.是否有一个好/干净/优雅/惯用的解决方案或我是否需要咬紧牙关并引入随后的'if'块?
简答:不.
我已经完成了
Match
你可能是,但编译器不知道.具体来说,生命周期目前与它们所定义的词法范围有关.您正在寻找的特征称为非词汇生命周期.它现在不稳定,但它计划在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; }
如果你引入一种新的类型和/或方法,这看起来不会太糟糕.作为奖励,有一个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时,原始代码按原样运行:
#![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 } }