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:
Short answer: No.
I'm done with the
Match
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.
As an example:
fn main() {
let mut s = String::from("hello");
let matched = &s[..];
println!("{}", matched);
s.clear();
println!("{}", s);
}
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);
}
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;
}
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;
}
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
}
}