2016-06-03 7 views
0

У меня есть вектор строк, и я хочу извлечь из них некоторые данные и создать из него структуру. Это выглядит примерно так:Могу ли я избавиться от «мута» здесь?

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 

Как вы можете видеть, я должен использовать mut для структуры. Есть ли способ сделать это без mut? Я хочу иметь возможность инициализировать структуру сразу, без mut. Или я могу рассмотреть другие варианты без mut.

+0

Уверен, что у вас есть причины для запроса, но обратите внимание, что в Rust 'mut' на самом деле не нахмурился - он просто не является значением по умолчанию и не должен использоваться, когда это не необходимо. Часто бывает, что создание чего-то изменяемого приведет к тому, что остальная часть кода будет проще и быстрее, и это то, что поощряет Rust. –

ответ

2

В чисто функциональном языке вам необходимо определить рекурсивную функцию. В Руст, это будет выглядеть следующим образом:

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

Обратите внимание, что есть еще в этом коде mut: мы должны определить str_iter, как изменяемые, так как вызов next() требует, чтобы приемник изменяемым.

В то время как внутренняя функция является хвостовой рекурсивной, Rust не гарантирует хвостовые вызовы, поэтому она может упасть с переполнением стека, если вход слишком велик. Лично я предпочел бы использовать mut здесь, как и в вашем исходном коде, тем более что mut в Rust не подразумевает никакого наложения псевдонимов, что устраняет целый класс потенциальных ошибок.

Смежные вопросы