2017-01-11 2 views
8

Я пытаюсь разобрать файл, используя регулярные выражения:Есть ли способ освободить привязку, прежде чем она выходит из сферы действия?

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

... но компилятор жалуется, потому что captures() метод RegEx «s имеет заем, который выдерживает в течение всей жизни матча:

error[E0502]: cannot borrow `line` as mutable because it is also borrowed as immutable 
    --> src/main.rs:58:13 
    | 
56 |   if let Some(m) = section_header_pattern.captures(&line).and_then(|c| c.get(1)) { 
    |               ---- immutable borrow occurs here 
... 
58 |    line.clear(); 
    |    ^^^^ mutable borrow occurs here 
59 |    continue; 
60 |   } 
    |   - immutable borrow ends here 

К моменту, когда я добираюсь до line.clear();, я закончил с Match и хотел очистить буфер и перейти к следующей строке в файле без дальнейшей обработки. Есть ли хорошее/чистое/элегантное/идиоматическое решение или мне нужно просто укусить пулю и ввести следующий блок «if»?

+0

дубликата http://stackoverflow.com/q/30243606/155423? – Shepmaster

+4

Не связано с вашим вопросом; почему вы используете '.eq ('? Я видел, как другие люди делают то же самое. В чем причина, почему вы избегаете '=='? – Shepmaster

+0

@Shepmaster Я не уверен, что они дубликаты, поскольку другой вопрос имеет дело с блок else (который у меня нет) и решается ранним возвратом. – steamer25

ответ

7

Короткий ответ: Нет

Я сделал с Match

Вы можете быть, но компилятор не знает, что. В частности, сроки жизни связаны с лексической сферой, в которой они определены. Волшебная функция, которую вы ищете, называется non-lexical lifetimes. Это не существует сейчас, но многие люди хотели бы этого.

В качестве примера:

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; 
} 
Смежные вопросы