2016-04-16 11 views
4

Rustを学ぶために、私は単純なパーサで作業を始めました。私はそれを働かせましたが、私は.clone()を使って私の構造体にデータを保存するような悪い習慣を使用しました。パーサーをリファクタリングしているときに不変として借用されているため、変数を可変として借りることはできません

今日私は、オブジェクトを複製するのではなくオブジェクトへの参照を使用するようにコードをリファクタリングし始めました。私はかなり遠く、これらの2つのエラーで立ち往生する前に得た:

error: cannot borrow 'm_list' as mutable because it is also borrowed as immutable [E0502] 

error: cannot borrow 'h_list' as mutable because it is also borrowed as immutable [E0502] 

のエラーについて読んだ後、私は非常に困惑しています。 Rustの借用チェッカーのバグだと言う人もいますが、99%は自分のコードのバグだと確信しています。

エラーがマニフェストコード:

mod utypes; 

use std::env; 
use std::fs::File; 
use std::io::BufRead; 
use std::io::BufReader; 
use std::error::Error; 

use utypes::*; 

fn main() {  

    let args: Vec<_> = env::args().collect(); 

    let file = match File::open(&args[1]) { 

     Ok(file) => file, 
     Err(why) => panic!("IO Error on line: {}, cause: {}", line!(), Error::description(&why)), 

    }; 
    let buffer = BufReader::new(file); 

    let mut m_list: Vec<Materia> = Vec::new(); 
    let mut h_list: Vec<Hora> = Vec::new(); 
    let mut t_list: Vec<Turno> = Vec::new(); 

    for line in buffer.lines() { 

     let l = line.unwrap(); 
     let spl_line: Vec<&str> = l.split(':').collect(); 

     if spl_line[0].starts_with('#') { continue; } 

     match spl_line[0] { 

      "mat" => { parse_mat(&mut m_list,spl_line) }, 
      "hra" => { parse_hra(&m_list,&mut h_list,spl_line) }, 
      "trn" => { parse_trn(&mut t_list,spl_line) }, 
      "tad" => { exec_tad(&h_list,&mut t_list,spl_line) }, 
      "" => continue, 
      _  => panic!("Unknown type identifier: {}.", spl_line[0]), 

     } 

    } 

    for turno in t_list.iter() { 

     println!("\nTurno: {}:\n", turno.nombre); 
     for dia in turno.dias.iter() { 

      print!("{:?}: ", dia.enum_id); 
      for hora in dia.horas.iter() { 

       print!("\n\t{} ", hora); 

      } 
      println!(""); 

     } 

    } 

    /* 
    println!("\nDEBUG INFO:\n"); 
    println!("{:?}", m_list); 
    println!("{:?}", h_list); 
    println!("{:?}", t_list); 
    */ 

} 

fn get_trn(t_list: &Vec<Turno>, gid: u32) -> Option<usize> { 

    for (i,trn) in t_list.iter().enumerate() { 

     if trn.id == gid { 

      return Some(i); 

     } 

    } 

    None 

} 

fn get_hra (h_list: &Vec<Hora>, gid: u32) -> Option<usize> { 

    for (i,hra) in h_list.iter().enumerate() { 

     if hra.id == gid { 

      return Some(i); 

     } 

    } 

    None 

} 

fn get_mat (m_list: &Vec<Materia>, gid: u32) -> Option<usize> { 

    for (i,mat) in m_list.iter().enumerate() { 

     if mat.id == gid { 

      return Some(i); 

     } 

    } 

    None 

} 

fn parse_mat<'a> (m_list: &'a mut Vec<Materia>, line: Vec<&str>) { 

    assert_eq!(4,line.len()); 

    let id: u32 = match line[1].parse::<u32>() { 

     Ok(id) => id, 
     Err(_) => panic!("Error parsing u32 at {}.", line!()), 

    }; 

    m_list.push(Materia::new(id,line[2].to_string(),line[3].to_string())); 

    } 

fn parse_hra<'a> (m_list: &'a Vec<Materia>, h_list: &mut Vec<Hora<'a>>, line: Vec<&str>) { 

    assert_eq!(5,line.len()); 

    let id: u32 = match line[1].parse::<u32>() { 

     Ok(id) => id, 
     Err(_) => panic!("Error parsing u32 at {}.", line!()), 

    }; 
    let start: u32 = match line[2].parse::<u32>() { 

     Ok(start) => start, 
     Err(_) => panic!("Error parsing u32 at {}.", line!()), 

    }; 
    let durat: u32 = match line[3].parse::<u32>() { 

     Ok(durat) => durat, 
     Err(_) => panic!("Error parsing u32 at {}.", line!()), 

    }; 
    let matid: u32 = match line[4].parse::<u32>() { 

     Ok(matid) => matid, 
     Err(_) => panic!("Error parsing u32 at {}.", line!()), 

    }; 
    let mat_i: usize = match get_mat(m_list,matid) { 

     Some(x) => x, 
     None  => panic!("Error matid not found in m_list!") 

    }; 

    h_list.push(Hora::new(id,start,durat,&m_list[mat_i])); 

} 

fn parse_trn<'a> (t_list: &mut Vec<Turno<'a>>, line: Vec<&str>) { 

    assert_eq!(3,line.len()); 

    let id: u32 = match line[1].parse::<u32>() { 

     Ok(id) => id, 
     Err(_) => panic!("Error parsing u32 at {}.", line!()), 

    }; 

    t_list.push(Turno::new(id,line[2].to_string())); 

} 

fn exec_tad<'a> (h_list: &'a Vec<Hora<'a>>, t_list: &mut Vec<Turno<'a>>, line: Vec<&str>) { 

    assert_eq!(4,line.len()); 

    let hid: u32 = match line[2].parse::<u32>(){ 

     Ok(hid) => hid, 
     Err(_) => panic!("Error parsing u32 at {}.", line!()), 

    }; 
    let tid: u32 = match line[3].parse::<u32>(){ 

     Ok(tid) => tid, 
     Err(_) => panic!("Error parsing u32 at {}.", line!()), 

    }; 

    let hra_i: usize = match get_hra(h_list,hid) { 

     Some(x) => x, 
     None => panic!("Error matid not found in m_list!") 

    }; 
    let trn_i: usize = match get_trn(t_list,tid) { 

     Some(x) => x, 
     None => panic!("Error matid not found in m_list!") 

    }; 

    match line[1] { 

     "Dom" => t_list[trn_i].addhra(Dias::Dom,&h_list[hra_i]), 
     "Lun" => t_list[trn_i].addhra(Dias::Lun,&h_list[hra_i]), 
     "Mar" => t_list[trn_i].addhra(Dias::Mar,&h_list[hra_i]), 
     "Mie" => t_list[trn_i].addhra(Dias::Mie,&h_list[hra_i]), 
     "Jue" => t_list[trn_i].addhra(Dias::Jue,&h_list[hra_i]), 
     "Vie" => t_list[trn_i].addhra(Dias::Vie,&h_list[hra_i]), 
     "Sab" => t_list[trn_i].addhra(Dias::Sab,&h_list[hra_i]), 
     _  => panic!("Unknown day error!") 

    } 

} 

そしてutypes.rs:

use std::fmt; 

//Dias 
#[derive(Debug)] 
pub enum Dias { 

    Dom, 
    Lun, 
    Mar, 
    Mie, 
    Jue, 
    Vie, 
    Sab, 

} 

//Materia 

#[derive(Debug)] 
pub struct Materia { 

    pub id: u32, 
    pub nombre: String, 
    pub profesor: String, 

} 

impl Materia { 

    pub fn new(i: u32, nom: String, prof: String) -> Materia { 

     Materia { 

      id: i, 
      nombre: nom, 
      profesor: prof, 


     } 

    } 
} 

//Hora 

#[derive(Debug,Clone)] 
pub struct Hora<'a> { 

    pub id: u32, 
    pub comienzo: u32, 
    pub duracion: u32, 
    pub materia: &'a Materia, 

} 

impl<'a> Hora<'a> { 

    pub fn new (id: u32, com: u32, dur: u32, mat: &'a Materia) -> Hora<'a> { 

     Hora { 

      id: id, 
      comienzo: com, 
      duracion: dur, 
      materia: mat, 

     } 

    } 

    pub fn fin (&self) -> u32 { 

     self.comienzo + self.duracion 

    } 

    pub fn fmt_time (tot: u32) -> String { 

     let min = (tot/60) % 60; 
     let hra = tot/3600; 

     format!("{:02}:{:02}", hra, min) 

    } 

} 

impl<'a> fmt::Display for Hora<'a> { 

    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 

     write!(f, "[{}-{}, {}]", Hora::fmt_time(self.comienzo), Hora::fmt_time(self.fin()), self.materia.nombre) 

    } 

} 

//Dia 

#[derive(Debug)] 
pub struct Dia<'a> { 

    pub enum_id: Dias, 
    pub nombre: String, 
    pub horas: Vec<&'a Hora<'a>>, 

} 

impl<'a> Dia<'a> { 

    pub fn new(ei: Dias, nom: String) -> Dia<'a> { 

     Dia { 

      enum_id: ei, 
      nombre: nom, 
      horas: Vec::new(), 

     } 

    } 

    pub fn addhra(&mut self, hra: &'a Hora<'a>){ 

     self.horas.push(hra); 

    } 

} 

//Turno 

#[derive(Debug)] 
pub struct Turno<'a> { 

    pub id: u32, 
    pub nombre: String, 
    pub dias: [Dia<'a>; 7], 

} 

impl<'a> Turno<'a> { 

    pub fn new(i: u32, nom: String) -> Turno<'a> { 

     Turno { 

      id: i, 
      nombre: nom, 
      dias: [ 

        Dia::new(Dias::Dom,"Domingo" .to_string()), 
        Dia::new(Dias::Lun,"Lunes" .to_string()), 
        Dia::new(Dias::Mar,"Martes" .to_string()), 
        Dia::new(Dias::Mie,"Miercoles".to_string()), 
        Dia::new(Dias::Jue,"Jueves" .to_string()), 
        Dia::new(Dias::Vie,"Viernes" .to_string()), 
        Dia::new(Dias::Sab,"Sabado" .to_string()) 

        ], 

     } 

    } 

    pub fn addhra(&mut self, dia: Dias, hra: &'a Hora<'a>) { 

     match dia { 

      Dias::Dom => self.dias[0].addhra(hra), 
      Dias::Lun => self.dias[1].addhra(hra), 
      Dias::Mar => self.dias[2].addhra(hra), 
      Dias::Mie => self.dias[3].addhra(hra), 
      Dias::Jue => self.dias[4].addhra(hra), 
      Dias::Vie => self.dias[5].addhra(hra), 
      Dias::Sab => self.dias[6].addhra(hra), 

     } 

    } 

} 

私は別で、にできるはずですので、変更可能な参照&mut m_listが機能した後parse_mat()リターンを終了だと思いますforループの繰り返し、parse_hra()を呼び出し、​​を問題なく通してください。

全エラー:

src/main.rs:36:39: 36:45 error: cannot borrow `m_list` as mutable because it is also borrowed as immutable [E0502] 
src/main.rs:36    "mat" => { parse_mat(&mut m_list,spl_line) }, 
               ^~~~~~ 
src/main.rs:37:35: 37:41 note: previous borrow of `m_list` occurs here; the immutable borrow prevents subsequent moves or mutable borrows of `m_list` until the borrow ends 
src/main.rs:37    "hra" => { parse_hra(&m_list,&mut h_list,spl_line) }, 
              ^~~~~~ 
src/main.rs:71:2: 71:2 note: previous borrow ends here 
src/main.rs:11 fn main() {  
      ... 
src/main.rs:71 } 
     ^
src/main.rs:37:47: 37:53 error: cannot borrow `h_list` as mutable because it is also borrowed as immutable [E0502] 
src/main.rs:37    "hra" => { parse_hra(&m_list,&mut h_list,spl_line) }, 
                 ^~~~~~ 
src/main.rs:39:34: 39:40 note: previous borrow of `h_list` occurs here; the immutable borrow prevents subsequent moves or mutable borrows of `h_list` until the borrow ends 
src/main.rs:39    "tad" => { exec_tad(&h_list,&mut t_list,spl_line) }, 
              ^~~~~~ 
src/main.rs:71:2: 71:2 note: previous borrow ends here 
src/main.rs:11 fn main() {  
      ... 
src/main.rs:71 } 
     ^

私は間違いのためにとても残念ネイティブスピーカーではありませんよ。

play-rust

+0

parse_hra/parse_mat/parse_trn/exec_tad&main/uses –

+0

@DemurRumed Dornを削除せずに、スタブメソッドを含む完全なエラーコードの例を含めてください。 – Darthkpo

+1

関数 'parse_hra'を使って' h_list'に 'm_list'の要素への参照を格納します。したがって、 'm_list'は' h_list'がスコープから外れると終了します。参照の代わりに 'Rc'を使うようにしてください。 – aSpex

答えて

1

@aSpexコメントは正しいです。

この問題を解決するには、HoraDiaの中の参照を対応するインデックスで置き換えることができます。それはあなたがまたフィールドm_listh_listt_listを持つ構造体を作成することができますので、彼らが一緒にkeepedさ

struct Hora { 
    materia: usize; //index in m_list 
} 

struct Dia { 
    horas: Vec<usize>; //indices in h_list 
} 

です。

RcおよびRefCellを使用するアプローチとの比較については、thisを参照してください。

関連する問題