Is there a way to release a binding before it goes out of scope?

后端 未结 1 656
心在旅途
心在旅途 2021-01-04 10: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:          


        
1条回答
  •  别那么骄傲
    2021-01-04 11:06

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

    0 讨论(0)
提交回复
热议问题