2016-06-03 4 views
0

Ich habe einen Vektor von Strings und ich möchte einige Daten aus ihnen extrahieren und eine Struktur daraus erstellen. Es sieht etwa so aus:Kann ich "mut" hier loswerden?

let mut my_struct = MyStruct::new(0, 0, 0); 
let regex1 = Regex::new("..."); 
let regex2 = Regex::new("..."); 

for s_iter in my_str_vec.iter() { 
    if regex1.is_match(s_iter) { 
     // parsing the value 
     // ......... 
     let var1 = regex1.captures("...."); 

     // and assign it to to a field of the struct instance 
     my_struct.field1 = var1; 
    } 

    // do the same thing for other fields each step in the loop 
    // each step only one regex gets triggered 

    if regex2.is_match(s_iter) { 
     // parsing the value 
     // ......... 
     let var2 = regex12.captures("...."); 

     // and assign it to to a field of the struct instance 
     my_struct.field2 = var2; 
    } 
} 

// now "my_struct" is now completely initialized 

Wie Sie sehen können, habe ich mut für die Struktur zu verwenden. Gibt es eine Möglichkeit, das ohne mut zu tun? Ich möchte in der Lage sein, die Struktur auf einmal zu initialisieren, ohne mut. Oder ich kann andere Optionen ohne mut auch betrachten.

+0

Ich bin sicher, Sie haben Ihre Gründe zu fragen, aber beachten Sie, dass in Rust 'mut' nicht wirklich verpönt ist - es ist einfach nicht die Standardeinstellung und sollte nicht verwendet werden, wenn nicht notwendig. Es ist oft der Fall, dass etwas, das veränderbar ist, den Rest des Codes einfacher und schneller macht, und das fördert Rust. –

Antwort

2

In einer rein funktionalen Sprache müssten Sie eine rekursive Funktion definieren. In Rust, würde es so aussehen:

fn parse(my_str_vec: Vec<&str>) -> MyStruct { 
    let my_struct = MyStruct::new(0, 0, 0); 
    let regex1 = Regex::new(...); 
    let regex2 = Regex::new(...); 

    fn process_next<I>(regex1: Regex, regex2: Regex, mut str_iter: I, my_struct: MyStruct) -> MyStruct 
     where I: Iterator, I::Item: AsRef<str> 
    { 
     match str_iter.next() { 
      Some(s_iter) => { 
       let my_struct = if regex1.is_match(s_iter.as_ref()) { 
        let var1 = regex1.captures("var1"); 
        MyStruct { field1: var1, ..my_struct } 
       } else if regex2.is_match(s_iter.as_ref()) { 
        let var2 = regex2.captures("var2"); 
        MyStruct { field2: var2, ..my_struct } 
       } else { 
        my_struct 
       }; 

       process_next(regex1, regex2, str_iter, my_struct) 
      } 
      None => my_struct 
     } 
    } 

    process_next(regex1, regex2, my_str_vec.iter(), my_struct) 
} 

Beachten Sie, dass nach wie vor gibt es eine mut in diesem Code: haben wir str_iter als wandelbar zu definieren, weil Aufruf next() den Empfänger erfordert wandelbar zu sein.

Während die innere Funktion tail rekursiv ist, garantiert Rust keine Tail-Aufrufe, so dass es bei einem Stack-Overflow zu einem Absturz kommen kann, wenn die Eingabe zu groß ist. Persönlich würde ich lieber mut hier verwenden, wie in Ihrem ursprünglichen Code, zumal mut in Rust kein Aliasing impliziert, was eine ganze Klasse potentieller Fehler beseitigt.